You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 05:30:03