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