upload_bg.py 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. # ##### BEGIN GPL LICENSE BLOCK #####
  2. #
  3. # This program is free software; you can redistribute it and/or
  4. # modify it under the terms of the GNU General Public License
  5. # as published by the Free Software Foundation; either version 2
  6. # of the License, or (at your option) any later version.
  7. #
  8. # This program is distributed in the hope that it will be useful,
  9. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. # GNU General Public License for more details.
  12. #
  13. # You should have received a copy of the GNU General Public License
  14. # along with this program; if not, write to the Free Software Foundation,
  15. # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  16. #
  17. # ##### END GPL LICENSE BLOCK #####
  18. if "bpy" in locals():
  19. from importlib import reload
  20. paths = reload(paths)
  21. append_link = reload(append_link)
  22. bg_blender = reload(bg_blender)
  23. utils = reload(utils)
  24. rerequests = reload(rerequests)
  25. else:
  26. from blenderkit import paths, append_link, bg_blender, utils, rerequests
  27. import sys, json, os, time
  28. import requests
  29. import logging
  30. import bpy
  31. BLENDERKIT_EXPORT_DATA = sys.argv[-1]
  32. def start_logging():
  33. logging.basicConfig()
  34. logging.getLogger().setLevel(logging.DEBUG)
  35. requests_log = logging.getLogger("requests.packages.urllib3")
  36. requests_log.setLevel(logging.DEBUG)
  37. requests_log.propagate = True
  38. def print_gap():
  39. print('\n\n\n\n')
  40. class upload_in_chunks(object):
  41. def __init__(self, filename, chunksize=1 << 13, report_name='file'):
  42. self.filename = filename
  43. self.chunksize = chunksize
  44. self.totalsize = os.path.getsize(filename)
  45. self.readsofar = 0
  46. self.report_name = report_name
  47. def __iter__(self):
  48. with open(self.filename, 'rb') as file:
  49. while True:
  50. data = file.read(self.chunksize)
  51. if not data:
  52. sys.stderr.write("\n")
  53. break
  54. self.readsofar += len(data)
  55. percent = self.readsofar * 1e2 / self.totalsize
  56. bg_blender.progress('uploading %s' % self.report_name, percent)
  57. # sys.stderr.write("\r{percent:3.0f}%".format(percent=percent))
  58. yield data
  59. def __len__(self):
  60. return self.totalsize
  61. def upload_file(upload_data, f):
  62. headers = utils.get_headers(upload_data['token'])
  63. version_id = upload_data['id']
  64. bg_blender.progress('uploading %s' % f['type'])
  65. upload_info = {
  66. 'assetId': version_id,
  67. 'fileType': f['type'],
  68. 'fileIndex': f['index'],
  69. 'originalFilename': os.path.basename(f['file_path'])
  70. }
  71. upload_create_url = paths.get_api_url() + 'uploads/'
  72. upload = rerequests.post(upload_create_url, json=upload_info, headers=headers, verify=True)
  73. upload = upload.json()
  74. #
  75. chunk_size = 1024 * 1024 * 2
  76. utils.pprint(upload)
  77. # file gets uploaded here:
  78. uploaded = False
  79. # s3 upload is now the only option
  80. for a in range(0, 5):
  81. if not uploaded:
  82. try:
  83. upload_response = requests.put(upload['s3UploadUrl'],
  84. data=upload_in_chunks(f['file_path'], chunk_size, f['type']),
  85. stream=True, verify=True)
  86. if upload_response.status_code == 200:
  87. uploaded = True
  88. else:
  89. print(upload_response.text)
  90. bg_blender.progress(f'Upload failed, retry. {a}')
  91. except Exception as e:
  92. print(e)
  93. bg_blender.progress('Upload %s failed, retrying' % f['type'])
  94. time.sleep(1)
  95. # confirm single file upload to bkit server
  96. upload_done_url = paths.get_api_url() + 'uploads_s3/' + upload['id'] + '/upload-file/'
  97. upload_response = rerequests.post(upload_done_url, headers=headers, verify=True)
  98. bg_blender.progress('finished uploading')
  99. return uploaded
  100. def upload_files(upload_data, files):
  101. uploaded_all = True
  102. for f in files:
  103. uploaded = upload_file(upload_data, f)
  104. if not uploaded:
  105. uploaded_all = False
  106. bg_blender.progress('finished uploading')
  107. return uploaded_all
  108. if __name__ == "__main__":
  109. try:
  110. bg_blender.progress('preparing scene - append data')
  111. with open(BLENDERKIT_EXPORT_DATA, 'r') as s:
  112. data = json.load(s)
  113. bpy.app.debug_value = data.get('debug_value', 0)
  114. export_data = data['export_data']
  115. upload_data = data['upload_data']
  116. upload_set = data['upload_set']
  117. if 'MAINFILE' in upload_set:
  118. bpy.data.scenes.new('upload')
  119. for s in bpy.data.scenes:
  120. if s.name != 'upload':
  121. bpy.data.scenes.remove(s)
  122. if export_data['type'] == 'MODEL':
  123. obnames = export_data['models']
  124. main_source, allobs = append_link.append_objects(file_name=data['source_filepath'],
  125. obnames=obnames,
  126. rotation=(0, 0, 0))
  127. g = bpy.data.collections.new(upload_data['name'])
  128. for o in allobs:
  129. g.objects.link(o)
  130. bpy.context.scene.collection.children.link(g)
  131. if export_data['type'] == 'SCENE':
  132. sname = export_data['scene']
  133. main_source = append_link.append_scene(file_name=data['source_filepath'],
  134. scenename=sname)
  135. bpy.data.scenes.remove(bpy.data.scenes['upload'])
  136. main_source.name = sname
  137. elif export_data['type'] == 'MATERIAL':
  138. matname = export_data['material']
  139. main_source = append_link.append_material(file_name=data['source_filepath'], matname=matname)
  140. elif export_data['type'] == 'BRUSH':
  141. brushname = export_data['brush']
  142. main_source = append_link.append_brush(file_name=data['source_filepath'], brushname=brushname)
  143. bpy.ops.file.pack_all()
  144. main_source.blenderkit.uploading = False
  145. fpath = os.path.join(data['temp_dir'], upload_data['assetBaseId'] + '.blend')
  146. bpy.ops.wm.save_as_mainfile(filepath=fpath, compress=True, copy=False)
  147. os.remove(data['source_filepath'])
  148. bg_blender.progress('preparing scene - open files')
  149. files = []
  150. if 'THUMBNAIL' in upload_set:
  151. files.append({
  152. "type": "thumbnail",
  153. "index": 0,
  154. "file_path": export_data["thumbnail_path"]
  155. })
  156. if 'MAINFILE' in upload_set:
  157. files.append({
  158. "type": "blend",
  159. "index": 0,
  160. "file_path": fpath
  161. })
  162. bg_blender.progress('uploading')
  163. uploaded = upload_files(upload_data, files)
  164. if uploaded:
  165. # mark on server as uploaded
  166. if 'MAINFILE' in upload_set:
  167. confirm_data = {
  168. "verificationStatus": "uploaded"
  169. }
  170. url = paths.get_api_url() + 'assets/'
  171. headers = utils.get_headers(upload_data['token'])
  172. url += upload_data["id"] + '/'
  173. r = rerequests.patch(url, json=confirm_data, headers=headers, verify=True) # files = files,
  174. bg_blender.progress('upload finished successfully')
  175. else:
  176. bg_blender.progress('upload failed.')
  177. except Exception as e:
  178. print(e)
  179. bg_blender.progress(e)
  180. sys.exit(1)