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
相关产品推荐
相关产品推荐

