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

Flask使用tempfile临时文件调用send_file返回报错解决方案问询

Flask使用tempfile配合send_file返回临时PDF解决方案

错误原因

  • 第一个AttributeError报错:你调用fp.read()拿到的是字节串对象,send_file要求传入的第一个参数是类文件对象(支持read方法)或者文件路径,字节串本身没有read方法,因此触发报错。
  • 第二个已关闭文件读取报错:如果直接传入fp对象,with上下文会在代码块执行结束(也就是return语句执行后)自动关闭临时文件,而Flask的send_file是在响应返回阶段才读取文件内容,此时临时文件已经被销毁关闭,因此触发报错。

可行解决方案

方案一:使用BytesIO替代磁盘临时文件(纯内存处理,无实体文件生成)

适合体积较小的PDF场景,全程在内存中处理,不需要操作磁盘,性能更高:

from io import BytesIO

fp = BytesIO()
PDF.dumps(fp, pdf)
fp.seek(0) # 重置文件指针到开头,避免读取内容为空
return send_file(fp, attachment_filename="invoice"+str(invoice["id"])+".pdf", as_attachment=True)

注意:必须调用seek(0)重置指针位置,否则send_file会从写入结束的位置开始读取,返回空文件。

方案二:使用NamedTemporaryFile配合请求钩子自动清理(适合大体积PDF)

如果PDF体积较大,内存存储压力高,可以使用带名称的磁盘临时文件,通过Flask的after_this_request钩子在请求结束后自动删除文件,不需要手动维护:

import tempfile
import os
from flask import after_this_request

tmp = tempfile.NamedTemporaryFile(delete=False, suffix='.pdf')
try:
    PDF.dumps(tmp, pdf)
    tmp.close() # 提前关闭文件解除占用,后续send_file读取文件路径即可

    @after_this_request
    def remove_tmp_file(response):
        try:
            os.remove(tmp.name)
        except:
            # 忽略删除错误,避免影响正常响应返回
            pass
        return response

    return send_file(tmp.name, attachment_filename="invoice"+str(invoice["id"])+".pdf", as_attachment=True)
except Exception as e:
    # 异常场景也要清理临时文件
    os.remove(tmp.name)
    raise e

内容的提问来源于stack exchange,提问作者elementmg

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 06:27:02