Flask使用send_file返回pymongo GridFS存储文件时出现损坏截断问题
问题根源
你调用file.read(2048)识别文件后缀后,GridFS返回的文件类对象的读写指针已经偏移到了第2048字节位置。后续send_file读取文件内容时会从当前指针位置开始读取,直接丢失了前2KB的文件头,所以会出现文件头部异常、总大小小于原始文件、无法正常打开的问题,你观察到的文件大小差刚好接近2KB也印证了这个判断。
解决方案
只需要在识别完文件后缀后,把文件指针重置到起始位置即可,修改后的代码如下:
@app.route("/record/download/<record_id>") def api_softwares_record_download(record_id): try: #... file = files_gridfs.find_one({"_id": record_id}) file_ext = filetype.guess_extension(file.read(2048)) # 新增这行重置文件指针到开头 file.seek(0) filename = "{}-{}{}".format( app["name"], record["version"], ".{}".format(file_ext) if file_ext else "", ) response = send_file(file, as_attachment=True, attachment_filename=filename) return response except ...
如果是小文件场景,也可以提前把文件内容读到内存中处理,避免指针操作遗漏:
from io import BytesIO @app.route("/record/download/<record_id>") def api_softwares_record_download(record_id): try: #... file = files_gridfs.find_one({"_id": record_id}) # 一次性读取完整文件内容到BytesIO file_content = BytesIO(file.read()) file_ext = filetype.guess_extension(file_content.read(2048)) # 重置BytesIO指针 file_content.seek(0) filename = "{}-{}{}".format( app["name"], record["version"], ".{}".format(file_ext) if file_ext else "", ) response = send_file(file_content, as_attachment=True, attachment_filename=filename) return response except ...
其他疑问解答
你既没有误用send_file(),也不需要更换为flask_pymongo:这个问题是文件类对象读写指针偏移的通用逻辑问题,和Flask本身的接口、pymongo的封装版本都没有关系,即使切换为flask_pymongo也会出现相同的问题。
内容的提问来源于stack exchange,提问作者283375
相关产品推荐
相关产品推荐

