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.

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