flask需手动实现断点续传:解析range头提取字节范围,返回206响应并设置content-range;用seek()和read()安全读取大文件指定段;上传端通过分块上传+合并,配合临时文件与状态管理;注意content-range格式、416错误处理及代理兼容性。

Flask 本身不内置断点续传支持,但可以通过标准 HTTP 头(Range、Content-Range、206 Partial Content)和文件系统操作手动实现。关键在于正确解析请求范围、校验文件状态、返回对应字节块,并保持客户端能持续拼接。
如何处理 Range 请求并返回 206 响应
客户端发起断点续传时,会在请求头中携带 Range: bytes=1024- 或 Range: bytes=1024-2047。Flask 需从中提取起始、结束位置,并确保响应状态码为 206、响应头含 Content-Range 和 Accept-Ranges: bytes。
- 用
request.headers.get("Range")获取原始 Range 字符串,再正则或字符串切分提取数值 - 若未提供
Range,直接返回200全量响应(兼容普通下载) - 结束位置未指定(如
bytes=1024-)时,需设为file_size - 1;超出文件大小则按实际截断 - 响应体必须是原始字节流(
io.BytesIO或open(..., "rb")的read()结果),不能经 JSON 序列化
如何安全读取大文件的指定字节段
避免把整个文件加载进内存,尤其对 GB 级上传/下载场景。应使用偏移量跳转 + 定长读取,配合 seek() 和 read() 控制 I/O。
图片提示词生成器?不止如此。 马甲系统 —— 把脑海中的画面,翻译成AI能理解的专业表达。 用得越多,它越懂你:首次需要多问几句确认方向,用久了几乎一说就懂。 用得越多,它越快:缓存机制让后续对话越来越省。 RAG进化:成功案例持续入库,越跑越聪明。 输入「新手指南」查看完整功能介绍
- 打开文件时用
open(filepath, "rb"),不要用文本模式 - 调用
f.seek(start_byte)跳转到起始位置,再f.read(end_byte - start_byte + 1)读取 - 务必检查
start_byte ,否则返回 <code>416 Requested Range Not Satisfiable - 若文件在读取中被删除或截断,
os.stat()可提前校验,或捕获OSError回退处理
如何支持上传端的断点续传(分块合并)
上传断点续传本质是“分块上传 + 合并”,需额外维护上传状态(如临时文件名、已接收块列表、总大小)。Flask 接口需区分初始化、追加、完成三类请求。
- 初始化:客户端 POST
/upload/init携带filename和total_size,服务端生成唯一upload_id并创建空临时文件(如/tmp/upload_{upload_id}.part) - 追加:客户端 PUT
/upload/chunk?upload_id=xxx&offset=1024,服务端用seek(offset)写入,同时记录该 offset 已写入 - 完成:客户端 POST
/upload/complete?upload_id=xxx,服务端校验所有块是否齐备(可选 MD5 分块校验),然后重命名为目标文件 - 临时文件建议加锁(
threading.Lock或基于文件名的简单互斥),防止同一upload_id并发写入错乱
容易忽略的边界与兼容性问题
浏览器、wget、curl 对 Range 解析略有差异;移动端 SDK 更可能静默降级。真正跑通需要验证多个客户端行为。
-
Content-Range响应头格式必须严格为bytes 1024-2047/10000(注意空格和斜杠),少一个字符就导致 Chrome 拒绝续传 - 某些代理或 CDN 会过滤或改写
206响应,建议在 Nginx 层显式开启underscores_in_headers on;并透传Range相关头 - 上传合并时若客户端崩溃,需配套清理机制(如定时扫描过期
.part文件),否则磁盘会被占满 - Flask 开发服务器(
app.run())不支持并发长连接,测试断点续传务必用gunicorn或waitress
断点续传的健壮性不在逻辑多复杂,而在每处 HTTP 头是否精准、每个文件偏移是否校验、每次写入是否幂等。最常出问题的是 Content-Range 格式错误和未处理 416 场景,这两处建议先写单元测试覆盖。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










