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.

file_manager.py 6.4 KiB

13 jaren geleden
13 jaren geleden
13 jaren geleden
13 jaren geleden
13 jaren geleden
13 jaren geleden
13 jaren geleden
13 jaren geleden
13 jaren geleden
13 jaren geleden
13 jaren geleden
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. # Copyright (c) 2012 Web Notes Technologies Pvt Ltd (http://erpnext.com)
  2. #
  3. # MIT License (MIT)
  4. #
  5. # Permission is hereby granted, free of charge, to any person obtaining a
  6. # copy of this software and associated documentation files (the "Software"),
  7. # to deal in the Software without restriction, including without limitation
  8. # the rights to use, copy, modify, merge, publish, distribute, sublicense,
  9. # and/or sell copies of the Software, and to permit persons to whom the
  10. # Software is furnished to do so, subject to the following conditions:
  11. #
  12. # The above copyright notice and this permission notice shall be included in
  13. # all copies or substantial portions of the Software.
  14. #
  15. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
  16. # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  17. # PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  18. # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
  19. # CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
  20. # OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  21. #
  22. from __future__ import unicode_literals
  23. import webnotes
  24. import os, conf
  25. def upload():
  26. # get record details
  27. dt = webnotes.form_dict.get('doctype')
  28. dn = webnotes.form_dict.get('docname')
  29. at_id = webnotes.form_dict.get('at_id')
  30. webnotes.response['type'] = 'iframe'
  31. filename = webnotes.form['filedata'].filename
  32. if not filename:
  33. webnotes.response['result'] = """
  34. <script type='text/javascript'>
  35. window.parent.wn.views.fomrview['%s'].frm.attachments.dialog.hide();
  36. window.parent.msgprint("Please select a file!");
  37. </script>""" % dt
  38. return
  39. # save
  40. fid, fname = save_uploaded()
  41. # save it in the form
  42. updated = False
  43. if fid:
  44. updated = add_file_list(dt, dn, fname, fid)
  45. if fid and updated:
  46. # refesh the form!
  47. # with the new modified timestamp
  48. webnotes.response['result'] = """
  49. <script type='text/javascript'>
  50. window.parent.wn.widgets.form.file_upload_done('%(dt)s', '%(dn)s', '%(fid)s', '%(fname)s', '%(at_id)s', '%(mod)s');
  51. window.parent.wn.views.formview['%(dt)s'].frm.show_doc('%(dn)s');
  52. </script>
  53. """ % {
  54. 'dt': dt,
  55. 'dn': dn,
  56. 'fid': fid,
  57. 'fname': fname.replace("'", "\\'"),
  58. 'at_id': at_id,
  59. 'mod': webnotes.conn.get_value(dt, dn, 'modified')
  60. }
  61. # -------------------------------------------------------
  62. def add_file_list(dt, dn, fname, fid):
  63. """
  64. udpate file_list attribute of the record
  65. """
  66. fl = webnotes.conn.get_value(dt, dn, 'file_list') or ''
  67. if fl:
  68. fl += '\n'
  69. # add new file id
  70. fl += fname + ',' + fid
  71. # save
  72. webnotes.conn.set_value(dt, dn, 'file_list', fl)
  73. return True
  74. def remove_all(dt, dn):
  75. """remove all files in a transaction"""
  76. file_list = webnotes.conn.get_value(dt, dn, 'file_list') or ''
  77. for afile in file_list.split('\n'):
  78. if afile:
  79. fname, fid = afile.split(',')
  80. remove_file(dt, dn, fid)
  81. def remove_file(dt, dn, fid):
  82. """Remove fid from the give file_list"""
  83. # get the old file_list
  84. fl = webnotes.conn.get_value(dt, dn, 'file_list') or ''
  85. new_fl = []
  86. fl = fl.split('\n')
  87. for f in fl:
  88. if f and f.split(',')[1]!=fid:
  89. new_fl.append(f)
  90. # delete
  91. delete_file(fid)
  92. # update the file_list
  93. webnotes.conn.set_value(dt, dn, 'file_list', '\n'.join(new_fl))
  94. # return the new timestamp
  95. return webnotes.conn.get_value(dt, dn, 'modified')
  96. def make_thumbnail(blob, size):
  97. from PIL import Image
  98. from cStringIO import StringIO
  99. fobj = StringIO(blob)
  100. image = Image.open(fobj)
  101. image.thumbnail((tn,tn*2), Image.ANTIALIAS)
  102. outfile = cStringIO.StringIO()
  103. image.save(outfile, 'JPEG')
  104. outfile.seek(0)
  105. fcontent = outfile.read()
  106. return fcontent
  107. def get_uploaded_content():
  108. # should not be unicode when reading a file, hence using webnotes.form
  109. if 'filedata' in webnotes.form:
  110. i = webnotes.form['filedata']
  111. webnotes.uploaded_filename, webnotes.uploaded_content = i.filename, i.file.read()
  112. return webnotes.uploaded_filename, webnotes.uploaded_content
  113. else:
  114. webnotes.msgprint('No File');
  115. return None, None
  116. def save_uploaded():
  117. webnotes.response['type'] = 'iframe'
  118. fname, content = get_uploaded_content()
  119. if content:
  120. fid = save_file(fname, content)
  121. return fid, fname
  122. else:
  123. return None, fname
  124. def save_file(fname, content, module=None):
  125. from webnotes.model.doc import Document
  126. from filecmp import cmp
  127. check_max_file_size(content)
  128. new_fname = write_file(content)
  129. # some browsers return the full path
  130. if '\\' in fname:
  131. fname = fname.split('\\')[-1]
  132. if '/' in fname:
  133. fname = fname.split('/')[-1]
  134. # we use - for versions, so remove them from the name!
  135. fname = fname.replace('-', '')
  136. fpath = os.path.join(get_files_path(), fname)
  137. if os.path.exists(fpath) and cmp(fpath, new_fname):
  138. # remove file, already exists!
  139. os.remove(new_fname)
  140. return fname
  141. else:
  142. # generate the ID (?)
  143. f = Document('File Data')
  144. f.file_name = fname
  145. f.save(1)
  146. # rename new file
  147. os.rename(new_fname, os.path.join(get_files_path(), f.name))
  148. return f.name
  149. def check_max_file_size(content):
  150. max_file_size = getattr(conf, 'max_file_size', 1000000)
  151. if len(content) > max_file_size:
  152. raise Exception, 'Maximum File Limit (%s MB) Crossed' % (int(max_file_size / 1000000))
  153. def write_file(content):
  154. """write file to disk with a random name"""
  155. # create account folder (if not exists)
  156. webnotes.create_folder(get_files_path())
  157. fname = os.path.join(get_files_path(), webnotes.generate_hash())
  158. # write the file
  159. with open(fname, 'w+') as f:
  160. f.write(content)
  161. return fname
  162. def get_file_system_name(fname):
  163. # get system name from File Data table
  164. return webnotes.conn.sql("""select name, file_name from `tabFile Data`
  165. where name=%s or file_name=%s""", (fname, fname))
  166. def delete_file(fid, verbose=0):
  167. """delete file from file system"""
  168. import os
  169. webnotes.conn.sql("delete from `tabFile Data` where name=%s", fid)
  170. path = os.path.join(get_files_path(), fid.replace('/','-'))
  171. if os.path.exists(path):
  172. os.remove(path)
  173. def get_file(fname):
  174. f = get_file_system_name(fname)
  175. if f:
  176. file_id = f[0][0].replace('/','-')
  177. file_name = f[0][1]
  178. else:
  179. file_id = fname
  180. file_name = fname
  181. # read the file
  182. import os
  183. with open(os.path.join(get_files_path(), file_id), 'r') as f:
  184. content = f.read()
  185. return [file_name, content]
  186. files_path = None
  187. def get_files_path():
  188. global files_path
  189. if not files_path:
  190. import os, conf
  191. files_path = os.path.join(os.path.dirname(os.path.abspath(conf.__file__)),
  192. 'public', 'files')
  193. return files_path