FastAPI UploadFile保存SpooledTemporaryFile为tar.gz文件出错问题
FastAPI UploadFile 保存SpooledTemporaryFile后tar.gz损坏的问题解决
问题原因
- 文件指针位置错误:
w+b模式的文件在FastAPI读取上传内容后,指针会停留在内容末尾。如果直接读取该文件保存到磁盘,会从指针当前位置开始读取,无法获取有效内容,导致生成的文件为空或不完整,自然无法被tar命令识别。 - SpooledTemporaryFile的内存缓存特性:该类默认先将数据存储在内存中,仅当数据量超过阈值(默认10240字节)时才写入磁盘临时文件。若未正确触发数据刷盘或重置指针,内存中的数据可能无法被完整读取,进而导致保存的文件损坏。
解决办法
核心操作是确保读取SpooledTemporaryFile时,文件指针处于起始位置,且完整读取所有内容,具体实现步骤如下:
- 重置文件指针到开头:读取UploadFile的文件对象前,调用
await file.seek(0)(FastAPI的UploadFile为异步对象,需使用await) - 完整读取文件内容:通过
await file.read()获取全部字节数据 - 用
wb模式写入目标文件:保证二进制内容写入格式正确
修正后的FastAPI代码示例
from fastapi import FastAPI, UploadFile, File app = FastAPI() @app.post("/upload-tar/") async def upload_tar_file(file: UploadFile = File(...)): # 重置文件指针到起始位置 await file.seek(0) # 读取完整的上传文件字节数据 file_content = await file.read() # 写入磁盘文件,使用wb模式确保二进制格式正确 save_path = "./saved_file.tar.gz" with open(save_path, "wb") as f: f.write(file_content) # 后续可执行解压操作,例如: # import subprocess # subprocess.run(["tar", "-xvf", save_path], check=True) return {"message": "文件保存成功,可正常解压"}
大文件处理优化
若上传文件体积较大,一次性读取到内存可能引发性能问题,可采用分块读写的方式:
@app.post("/upload-large-tar/") async def upload_large_tar(file: UploadFile = File(...)): await file.seek(0) save_path = "./large_file.tar.gz" chunk_size = 1024 * 1024 # 按1MB分块读取 with open(save_path, "wb") as f: while chunk := await file.read(chunk_size): f.write(chunk) return {"message": "大文件保存成功"}
内容的提问来源于stack exchange,提问作者Elijah Crum
相关产品推荐
相关产品推荐

