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 19 20if "bpy" in locals(): 21 from importlib import reload 22 23 paths = reload(paths) 24 append_link = reload(append_link) 25 bg_blender = reload(bg_blender) 26 utils = reload(utils) 27 rerequests = reload(rerequests) 28else: 29 from blenderkit import paths, append_link, bg_blender, utils, rerequests 30 31import sys, json, os, time 32import requests 33import logging 34 35import bpy 36 37BLENDERKIT_EXPORT_DATA = sys.argv[-1] 38 39 40def start_logging(): 41 logging.basicConfig() 42 logging.getLogger().setLevel(logging.DEBUG) 43 requests_log = logging.getLogger("requests.packages.urllib3") 44 requests_log.setLevel(logging.DEBUG) 45 requests_log.propagate = True 46 47 48def print_gap(): 49 print('\n\n\n\n') 50 51 52class upload_in_chunks(object): 53 def __init__(self, filename, chunksize=1 << 13, report_name='file'): 54 self.filename = filename 55 self.chunksize = chunksize 56 self.totalsize = os.path.getsize(filename) 57 self.readsofar = 0 58 self.report_name = report_name 59 60 def __iter__(self): 61 with open(self.filename, 'rb') as file: 62 while True: 63 data = file.read(self.chunksize) 64 if not data: 65 sys.stderr.write("\n") 66 break 67 self.readsofar += len(data) 68 percent = self.readsofar * 1e2 / self.totalsize 69 bg_blender.progress('uploading %s' % self.report_name, percent) 70 # sys.stderr.write("\r{percent:3.0f}%".format(percent=percent)) 71 yield data 72 73 def __len__(self): 74 return self.totalsize 75 76 77def upload_file(upload_data, f): 78 headers = utils.get_headers(upload_data['token']) 79 version_id = upload_data['id'] 80 bg_blender.progress('uploading %s' % f['type']) 81 upload_info = { 82 'assetId': version_id, 83 'fileType': f['type'], 84 'fileIndex': f['index'], 85 'originalFilename': os.path.basename(f['file_path']) 86 } 87 upload_create_url = paths.get_api_url() + 'uploads/' 88 upload = rerequests.post(upload_create_url, json=upload_info, headers=headers, verify=True) 89 upload = upload.json() 90 # 91 chunk_size = 1024 * 1024 * 2 92 utils.pprint(upload) 93 # file gets uploaded here: 94 uploaded = False 95 # s3 upload is now the only option 96 for a in range(0, 5): 97 if not uploaded: 98 try: 99 upload_response = requests.put(upload['s3UploadUrl'], 100 data=upload_in_chunks(f['file_path'], chunk_size, f['type']), 101 stream=True, verify=True) 102 103 if upload_response.status_code == 200: 104 uploaded = True 105 else: 106 print(upload_response.text) 107 bg_blender.progress(f'Upload failed, retry. {a}') 108 except Exception as e: 109 print(e) 110 bg_blender.progress('Upload %s failed, retrying' % f['type']) 111 time.sleep(1) 112 113 # confirm single file upload to bkit server 114 upload_done_url = paths.get_api_url() + 'uploads_s3/' + upload['id'] + '/upload-file/' 115 upload_response = rerequests.post(upload_done_url, headers=headers, verify=True) 116 117 bg_blender.progress('finished uploading') 118 119 return uploaded 120 121 122def upload_files(upload_data, files): 123 uploaded_all = True 124 for f in files: 125 uploaded = upload_file(upload_data, f) 126 if not uploaded: 127 uploaded_all = False 128 bg_blender.progress('finished uploading') 129 return uploaded_all 130 131 132if __name__ == "__main__": 133 134 135 try: 136 bg_blender.progress('preparing scene - append data') 137 with open(BLENDERKIT_EXPORT_DATA, 'r') as s: 138 data = json.load(s) 139 140 bpy.app.debug_value = data.get('debug_value', 0) 141 export_data = data['export_data'] 142 upload_data = data['upload_data'] 143 144 upload_set = data['upload_set'] 145 if 'MAINFILE' in upload_set: 146 bpy.data.scenes.new('upload') 147 for s in bpy.data.scenes: 148 if s.name != 'upload': 149 bpy.data.scenes.remove(s) 150 151 if export_data['type'] == 'MODEL': 152 obnames = export_data['models'] 153 main_source, allobs = append_link.append_objects(file_name=data['source_filepath'], 154 obnames=obnames, 155 rotation=(0, 0, 0)) 156 g = bpy.data.collections.new(upload_data['name']) 157 for o in allobs: 158 g.objects.link(o) 159 bpy.context.scene.collection.children.link(g) 160 if export_data['type'] == 'SCENE': 161 sname = export_data['scene'] 162 main_source = append_link.append_scene(file_name=data['source_filepath'], 163 scenename=sname) 164 bpy.data.scenes.remove(bpy.data.scenes['upload']) 165 main_source.name = sname 166 elif export_data['type'] == 'MATERIAL': 167 matname = export_data['material'] 168 main_source = append_link.append_material(file_name=data['source_filepath'], matname=matname) 169 170 elif export_data['type'] == 'BRUSH': 171 brushname = export_data['brush'] 172 main_source = append_link.append_brush(file_name=data['source_filepath'], brushname=brushname) 173 174 bpy.ops.file.pack_all() 175 176 main_source.blenderkit.uploading = False 177 fpath = os.path.join(data['temp_dir'], upload_data['assetBaseId'] + '.blend') 178 179 bpy.ops.wm.save_as_mainfile(filepath=fpath, compress=True, copy=False) 180 os.remove(data['source_filepath']) 181 182 bg_blender.progress('preparing scene - open files') 183 184 files = [] 185 if 'THUMBNAIL' in upload_set: 186 files.append({ 187 "type": "thumbnail", 188 "index": 0, 189 "file_path": export_data["thumbnail_path"] 190 }) 191 if 'MAINFILE' in upload_set: 192 files.append({ 193 "type": "blend", 194 "index": 0, 195 "file_path": fpath 196 }) 197 198 bg_blender.progress('uploading') 199 200 uploaded = upload_files(upload_data, files) 201 202 if uploaded: 203 # mark on server as uploaded 204 if 'MAINFILE' in upload_set: 205 confirm_data = { 206 "verificationStatus": "uploaded" 207 } 208 209 url = paths.get_api_url() + 'assets/' 210 211 headers = utils.get_headers(upload_data['token']) 212 213 url += upload_data["id"] + '/' 214 215 r = rerequests.patch(url, json=confirm_data, headers=headers, verify=True) # files = files, 216 217 bg_blender.progress('upload finished successfully') 218 else: 219 bg_blender.progress('upload failed.') 220 221 except Exception as e: 222 print(e) 223 bg_blender.progress(e) 224 sys.exit(1) 225