如何在Python FastAPI中实现大文件的流式上传与断点续传?

星辰姑娘_3406

星辰姑娘_3406

2026-06-27

201人浏览

原创

FastAPI 的 UploadFile 不支持断点续传,需用 Request 直接读取流并手动解析 Content-Range、管理 upload_id 状态、实现流式写入与偏移校验,同时配置 Nginx 关闭缓冲并延长超时。

如何在python fastapi中实现大文件的流式上传与断点续传?

FastAPI 中 UploadFile 默认不支持断点续传,必须自己处理 HTTP 头和分块逻辑

FastAPI 的 UploadFile 本质是读取整个 request.body 到内存或临时文件,它不解析 Content-Range、Upload-ID 等断点续传必需头,也不维护上传状态。想实现断点续传,得绕过 UploadFile,直接读取原始请求流,并手动解析分块信息。

典型错误是试图在依赖中写 file: UploadFile = File(...) 然后去读 file.file.seek() —— 这行不通,因为 FastAPI 已经消费完 body,且 UploadFile.file 是 SpooledTemporaryFile,不支持随机读写,更无法响应客户端的续传请求。

  • 必须用 Request 对象直接接收原始字节流
  • 需校验并解析 Content-Range 头(如 bytes 1024-2047/5000000)
  • 需提取并校验客户端传来的唯一标识(如 X-Upload-ID 或 URL path 中的 upload_id)
  • 服务端要自行管理每个上传 ID 对应的临时文件路径、已写入偏移、总大小等元数据

用 Request + 文件系统实现流式写入与偏移校验

核心是把 request.stream() 当作异步迭代器,按 chunk 读取,再根据 Content-Range 定位写入位置。不要一次性 await request.body(),否则大文件会 OOM。

示例关键逻辑:

from fastapi import Request, HTTPException
import os
<p>async def handle_chunk_upload(request: Request):
upload_id = request.headers.get("X-Upload-ID")
content_range = request.headers.get("Content-Range")</p><pre class="brush:php;toolbar:false;">if not upload_id or not content_range:
    raise HTTPException(400, "Missing X-Upload-ID or Content-Range")

# 解析 range: bytes 1024-2047/5000000 → (start, end, total)
try:
    _, ranges = content_range.split(" ", 1)
    byte_part, total_part = ranges.split("/")
    start, end = map(int, byte_part.split("-"))
    total_size = int(total_part)
except (ValueError, IndexError):
    raise HTTPException(400, "Invalid Content-Range format")

file_path = f"/tmp/uploads/{upload_id}"
os.makedirs(os.path.dirname(file_path), exist_ok=True)

# 检查是否允许该偏移写入(防乱序、越界)
if start != os.path.getsize(file_path) if os.path.exists(file_path) else 0:
    raise HTTPException(409, "Offset mismatch: client must resume from current size")

# 流式写入
async for chunk in request.stream():
    with open(file_path, "ab") as f:
        f.write(chunk)

注意:上面示例未加锁,高并发下多个分块同时写同一文件会出错。生产环境必须用文件锁(如 flock)或改用数据库记录每个分块的写入状态。

断点续传需要客户端和服务端约定一致的重试与状态查询接口

光能接收分块不够,客户端需要能随时问:“这个 upload_id 当前传到哪了?” 否则网络中断后无法知道从哪续。

python学习
python学习

Python 编程学习助手 skill,面向零基础用户。 当用户表达以下意图时触发: - 学习 Python 基础概念(变量、数据类型、循环、函数、类等) - 请求 Python 练习题或测验 - 请求审查或调试 Python 代码 - 请求 Python 项目实战指导(爬虫、数据分析、Web 开发等入门项目) - 泛化表述如"教我 Python""我想学编程""Python 怎么写""帮我学 Python" 此 skill

下载
  • 提供 GET /upload/{upload_id}/status 接口,返回 {"offset": 123456, "total": 10485760}
  • 客户端首次上传时用 POST /upload/init 获取新 upload_id 和预分配的 total(可选)
  • 上传完成后再调用 POST /upload/{upload_id}/complete 做校验(如 MD5)、重命名、触发后续处理
  • 所有接口都必须校验 upload_id 是否合法、是否过期(建议加 TTL,比如 24 小时自动清理)

常见坑:状态接口返回的 offset 直接用 os.path.getsize() —— 如果写入中途崩溃,文件可能残留脏数据,应额外维护一个元数据 JSON 文件(如 {upload_id}.meta)记录已确认写入的 offset。

大文件上传必须配 Nginx 反向代理超时与缓冲区调整

FastAPI 自身不设上传超时,但 Nginx 默认 60 秒超时、单次请求体上限 1MB,不调就必然失败。

在 Nginx 配置里至少加这几项:

location /upload/ {
    client_max_body_size 2G;
    client_body_timeout 3600;
    proxy_read_timeout 3600;
    proxy_send_timeout 3600;
    proxy_buffering off;  # 关键:避免 Nginx 缓存整个 body 再转发
    proxy_pass http://fastapi_backend;
}

如果漏掉 proxy_buffering off,Nginx 会等整个文件收完才发给 FastAPI,彻底失去流式意义;而 client_body_timeout 必须足够长,否则慢速上传(如移动网络)会被直接断连。

另外,若用 uvicorn 启动,别用 --limit-concurrency 过严,它会阻塞后续请求,导致状态查询接口也卡住 —— 断点续传依赖低延迟的状态反馈。

大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

nginx 配置 python

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
python打包成可执行文件
python打包成可执行文件

本专题为大家带来python打包成可执行文件相关的文章,大家可以免费的下载体验。

2023.07.20

1771

4

python能做什么
python能做什么

python能做的有:可用于开发基于控制台的应用程序、多媒体部分开发、用于开发基于Web的应用程序、使用python处理数据、系统编程等等。本专题为大家提供python相关的各种文章、以及下载和课程。

2023.07.25

4644

7

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.07.31

1749

3

python教程
python教程

Python已成为一门网红语言,即使是在非编程开发者当中,也掀起了一股学习的热潮。本专题为大家带来python教程的相关文章,大家可以免费体验学习。

2023.08.03

27517

23

python环境变量的配置
python环境变量的配置

Python是一种流行的编程语言,被广泛用于软件开发、数据分析和科学计算等领域。在安装Python之后,我们需要配置环境变量,以便在任何位置都能够访问Python的可执行文件。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.04

3327

5

python eval
python eval

eval函数是Python中一个非常强大的函数,它可以将字符串作为Python代码进行执行,实现动态编程的效果。然而,由于其潜在的安全风险和性能问题,需要谨慎使用。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.04

3327

5

scratch和python区别
scratch和python区别

scratch和python的区别:1、scratch是一种专为初学者设计的图形化编程语言,python是一种文本编程语言;2、scratch使用的是基于积木的编程语法,python采用更加传统的文本编程语法等等。本专题为大家提供scratch和python相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.11

1203

5

python合并两个列表
python合并两个列表

Python是一种强大的编程语言,具有许多方便的功能和工具。在Python中,有多种方法可以合并两个列表。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.10

596

4

python是前端还是后端
python是前端还是后端

Python属于前端也属于后端,其灵活性和丰富的生态系统使得开发人员能够在不同的领域中灵活运用。本专题为大家提供python相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.11

2583

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Uvicorn官方安装与入门手册
Uvicorn官方安装与入门手册

共0课时 | 0人学习

Python uv官方项目管理指南
Python uv官方项目管理指南

共0课时 | 0人学习

Python uv官方安装与入门文档
Python uv官方安装与入门文档

共0课时 | 0人学习