问题
上传的文件放在表单上传如果过大,会导致服务端内存溢出,所以需要客户端将参数放到header里,文件放到body里传输,服务端流式接收body的内容
- 客户端代码
data = {'file_size':'xxxx','file_md5':'xxxx','file_id':'xxxxx'}
filename=‘xxxxx’
storage_url = "http://xxx"
with open(filename, 'rb') as f:
res = requests.post(storage_url, headers=data, data=f)
-
服务端代码
需要使用到
tornado.web.stream_request_body
装饰器
@tornado.web.stream_request_body
class BigformUploadHandler(web.RequestHandler):
executor = ThreadPoolExecutor(thread_pool_size)
save_name = None
save_seek = 0
def prepare(self):
try:
headers = self.request.headers
print(headers)
file_id = headers["file_id"]
redis_data = loads(redis_ins.get(file_id))
if redis_data:
storage_path = redis_data["storage_path"]
self.save_name = os.path.join(storage_path, file_id)
except Exception:
run_log.error(traceback.format_exc())
def data_received(self,chunk):
if self.save_name:
if not os.path.exists(self.save_name):
with open(self.save_name, 'wb+') as up:
pass
with open(self.save_name, 'rb+') as up:
up.seek(self.save_seek)
up.write(chunk)
self.save_seek = self.save_seek + len(chunk)
@tornado.web.asynchronous
@tornado.gen.coroutine
def post(self):
values = {}
result = {"return_code": 500,"error_info":""}
try:
headers = self.request.headers
values["file_md5"] = headers["file_md5"]
values["file_size"] = headers["file_size"]
values["file_id"] = headers["file_id"]
# 从redis获取存储路径
redis_data = loads(redis_ins.get(values["file_id"]))
values["storage_path"] = redis_data["storage_path"]
filename = os.path.join(values["storage_path"], values["file_id"])
values["filename"] = filename
result = yield self.do_upload_form(values)
except Exception:
run_log.error(traceback.format_exc())
finally:
if result["return_code"] == 200:
self.write(dumps(result))
else:
self.set_status(500)
@run_on_executor
def do_upload_form(self, values):
result = {"return_code": 500, "error_info": ""}
try:
if os.path.exists(values["filename"]):
md5 = str(get_md5(values["filename"]))
if values["file_md5"] == md5:
result['return_code']=200
except Exception:
run_log.error(traceback.format_exc())
finally:
return result