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

FastAPI UploadFile保存SpooledTemporaryFile为tar.gz文件出错问题

FastAPI UploadFile 保存SpooledTemporaryFile后tar.gz损坏的问题解决

问题原因

  • 文件指针位置错误:w+b模式的文件在FastAPI读取上传内容后,指针会停留在内容末尾。如果直接读取该文件保存到磁盘,会从指针当前位置开始读取,无法获取有效内容,导致生成的文件为空或不完整,自然无法被tar命令识别。
  • SpooledTemporaryFile的内存缓存特性:该类默认先将数据存储在内存中,仅当数据量超过阈值(默认10240字节)时才写入磁盘临时文件。若未正确触发数据刷盘或重置指针,内存中的数据可能无法被完整读取,进而导致保存的文件损坏。

解决办法

核心操作是确保读取SpooledTemporaryFile时,文件指针处于起始位置,且完整读取所有内容,具体实现步骤如下:

  1. 重置文件指针到开头:读取UploadFile的文件对象前,调用await file.seek(0)(FastAPI的UploadFile为异步对象,需使用await)
  2. 完整读取文件内容:通过await file.read()获取全部字节数据
  3. 用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 23:15:57