You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

преди 13 години
преди 13 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 13 години
преди 13 години
преди 13 години
преди 12 години
преди 13 години
преди 12 години
преди 12 години
преди 13 години
преди 13 години
преди 12 години
преди 13 години
преди 12 години
преди 13 години
преди 13 години
преди 13 години
преди 12 години
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. # Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
  2. # MIT License. See license.txt
  3. from __future__ import unicode_literals
  4. import webnotes
  5. import os, conf
  6. from webnotes.utils import cstr, get_path, cint
  7. from webnotes import _
  8. class MaxFileSizeReachedError(webnotes.ValidationError): pass
  9. def upload():
  10. # get record details
  11. dt = webnotes.form_dict.doctype
  12. dn = webnotes.form_dict.docname
  13. file_url = webnotes.form_dict.file_url
  14. filename = webnotes.form_dict.filename
  15. if not filename and not file_url:
  16. webnotes.msgprint(_("Please select a file or url"),
  17. raise_exception=True)
  18. # save
  19. if filename:
  20. filedata = save_uploaded(dt, dn)
  21. elif file_url:
  22. filedata = save_url(file_url, dt, dn)
  23. return {"fid": filedata.name, "filename": filedata.file_name or filedata.file_url }
  24. def save_uploaded(dt, dn):
  25. fname, content = get_uploaded_content()
  26. if content:
  27. return save_file(fname, content, dt, dn)
  28. else:
  29. raise Exception
  30. def save_url(file_url, dt, dn):
  31. if not (file_url.startswith("http://") or file_url.startswith("https://")):
  32. webnotes.msgprint("URL must start with 'http://' or 'https://'")
  33. return None, None
  34. f = webnotes.bean({
  35. "doctype": "File Data",
  36. "file_url": file_url,
  37. "attached_to_doctype": dt,
  38. "attached_to_name": dn
  39. })
  40. f.ignore_permissions = True
  41. f.insert();
  42. return f.doc
  43. def get_uploaded_content():
  44. # should not be unicode when reading a file, hence using webnotes.form
  45. if 'filedata' in webnotes.form_dict:
  46. import base64
  47. webnotes.uploaded_content = base64.b64decode(webnotes.form_dict.filedata)
  48. webnotes.uploaded_filename = webnotes.form_dict.filename
  49. return webnotes.uploaded_filename, webnotes.uploaded_content
  50. else:
  51. webnotes.msgprint('No File')
  52. return None, None
  53. def save_file(fname, content, dt, dn):
  54. import filecmp
  55. files_path = get_files_path()
  56. file_size = check_max_file_size(content)
  57. temp_fname = write_file(content)
  58. fname = scrub_file_name(fname)
  59. fpath = os.path.join(files_path, fname)
  60. fname_parts = fname.split(".", -1)
  61. main = ".".join(fname_parts[:-1])
  62. extn = fname_parts[-1]
  63. versions = get_file_versions(files_path, main, extn)
  64. if versions:
  65. found_match = False
  66. for version in versions:
  67. if filecmp.cmp(os.path.join(files_path, version), temp_fname):
  68. # remove new file, already exists!
  69. os.remove(temp_fname)
  70. fname = version
  71. found_match = True
  72. break
  73. if not found_match:
  74. # get_new_version name
  75. fname = get_new_fname_based_on_version(files_path, main, extn, versions)
  76. # rename
  77. os.rename(temp_fname, os.path.join(files_path, fname))
  78. else:
  79. # rename new file
  80. os.rename(temp_fname, os.path.join(files_path, fname))
  81. f = webnotes.bean({
  82. "doctype": "File Data",
  83. "file_name": fname,
  84. "attached_to_doctype": dt,
  85. "attached_to_name": dn,
  86. "file_size": file_size
  87. })
  88. f.ignore_permissions = True
  89. f.insert();
  90. return f.doc
  91. def get_file_versions(files_path, main, extn):
  92. return filter(lambda f: f.startswith(main) and f.endswith(extn), os.listdir(files_path))
  93. def get_new_fname_based_on_version(files_path, main, extn, versions):
  94. versions.sort()
  95. if "-" in versions[-1]:
  96. version = cint(versions[-1].split("-")[-1]) or 1
  97. else:
  98. version = 1
  99. new_fname = main + "-" + str(version) + "." + extn
  100. while os.path.exists(os.path.join(files_path, new_fname)):
  101. version += 1
  102. new_fname = main + "-" + str(version) + "." + extn
  103. if version > 100:
  104. webnotes.msgprint("Too many versions", raise_exception=True)
  105. return new_fname
  106. def scrub_file_name(fname):
  107. if '\\' in fname:
  108. fname = fname.split('\\')[-1]
  109. if '/' in fname:
  110. fname = fname.split('/')[-1]
  111. return fname
  112. def check_max_file_size(content):
  113. max_file_size = getattr(conf, 'max_file_size', 1000000)
  114. file_size = len(content)
  115. if file_size > max_file_size:
  116. webnotes.msgprint(_("File size exceeded the maximum allowed size"),
  117. raise_exception=MaxFileSizeReachedError)
  118. return file_size
  119. def write_file(content):
  120. """write file to disk with a random name (to compare)"""
  121. # create account folder (if not exists)
  122. webnotes.create_folder(get_files_path())
  123. fname = os.path.join(get_files_path(), webnotes.generate_hash())
  124. # write the file
  125. with open(fname, 'w+') as f:
  126. f.write(content)
  127. return fname
  128. def remove_all(dt, dn):
  129. """remove all files in a transaction"""
  130. try:
  131. for fid in webnotes.conn.sql_list("""select name from `tabFile Data` where
  132. attached_to_doctype=%s and attached_to_name=%s""", (dt, dn)):
  133. remove_file(fid)
  134. except Exception, e:
  135. if e.args[0]!=1054: raise e # (temp till for patched)
  136. def remove_file(fid):
  137. """Remove file and File Data entry"""
  138. webnotes.delete_doc("File Data", fid)
  139. def get_file_system_name(fname):
  140. # get system name from File Data table
  141. return webnotes.conn.sql("""select name, file_name from `tabFile Data`
  142. where name=%s or file_name=%s""", (fname, fname))
  143. def get_file(fname):
  144. f = get_file_system_name(fname)
  145. if f:
  146. file_name = f[0][1]
  147. else:
  148. file_name = fname
  149. # read the file
  150. import os
  151. with open(os.path.join(get_files_path(), file_name), 'r') as f:
  152. content = f.read()
  153. return [file_name, content]
  154. files_path = None
  155. def get_files_path():
  156. global files_path
  157. if not files_path:
  158. files_path = get_path("public", "files")
  159. return files_path