为何临时目录在with块返回前被删除?FastAPI文件返回问题
解决FastAPI返回openpyxl生成的Excel文件时临时文件提前被删除的问题
你遇到的问题核心是TemporaryDirectory的with上下文会在代码块执行完成后立即删除目录及其中的文件,但FastAPI的FileResponse是在响应阶段才去读取文件——此时文件已经被清理,所以抛出文件不存在的错误。
方案一:用BackgroundTasks延迟清理临时目录
放弃with语句手动管理临时目录,借助FastAPI的BackgroundTasks在响应返回给客户端后再执行清理操作:
from fastapi import BackgroundTasks, FileResponse from tempfile import TemporaryDirectory import os import shutil from openpyxl import Workbook def cleanup_temp_dir(tmp_dir_path: str): shutil.rmtree(tmp_dir_path) @app.get("/export-excel") def export_excel(background_tasks: BackgroundTasks): # 手动创建临时目录,不使用with上下文 tmp_dir = TemporaryDirectory() file_path = os.path.join(tmp_dir.name, f"{id}-export.xlsx") # 保存Excel文件到临时目录 wb = Workbook() wb.save(file_path) # 添加后台清理任务 background_tasks.add_task(cleanup_temp_dir, tmp_dir.name) return FileResponse( path=file_path, media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", filename=f"{id}-export.xlsx" )
方案二:直接返回内存中的文件字节流(推荐)
不需要创建临时文件,将Excel文件写入内存缓冲区,直接返回字节流,彻底避免临时文件管理问题:
from fastapi import Response import io from openpyxl import Workbook @app.get("/export-excel") def export_excel(): buffer = io.BytesIO() # 将Excel写入内存缓冲区 wb = Workbook() wb.save(buffer) # 重置缓冲区指针到起始位置 buffer.seek(0) return Response( content=buffer.getvalue(), media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", headers={ "Content-Disposition": f"attachment; filename={id}-export.xlsx" } )
说明
- 方案二更高效,无需磁盘IO操作,也不用处理临时文件的生命周期,是优先推荐的实现方式。
- 方案一适合需要临时文件做后续额外操作的场景,但要注意异常处理:如果文件保存失败,需手动调用清理函数避免残留临时文件。
内容的提问来源于stack exchange,提问作者NMITIMEN
相关产品推荐
相关产品推荐

