后端需通过filename、chunkIndex、totalChunks精准识别分片,强制form-data传输并校验唯一性;流式合并+前置校验防卡死/爆盘;断点续传须返回明确已传索引;并发下解耦接收与落盘,用队列+分布式锁保障可靠性。

前端传来的分片怎么在后端识别和存好
分片上传不是把文件随便切几块扔过来就行,后端得靠 filename、chunkIndex、totalChunks 这几个关键字段对齐上下文。缺一个,合并时就可能串片或漏片。
常见错误是只校验 filename,结果同名文件并发上传时,不同用户的分片混在一起;或者前端没传 chunkIndex(比如用 query string 传成 ?index=0 却忘了转成整数),导致排序错乱。
- 强制要求前端通过 form-data 的字段传
filename、chunkIndex(int)、totalChunks(int),不接受 URL 参数替代 - 用
filename+md5(file_content)做临时分片唯一键(避免同名不同内容覆盖) - 分片先写入临时目录(如
/tmp/uploads/{upload_id}/{chunkIndex}),不直接进最终路径 - 单个分片大小建议控制在 2–10 MB,太小增加 IO 次数,太大拖慢单次请求响应
Python 合并分片时怎么避免卡死或磁盘爆满
用 open(..., 'ab') 循环追加写,看着简单,但大文件下容易出问题:如果某一分片损坏或重复上传,追加进去就是脏数据;更危险的是,一次性把所有分片读进内存再拼接(比如用 b''.join(chunks)),1 GB 文件分 100 片,光 Python 对象就吃掉几 GB 内存。
真正安全的合并方式是「流式拼接」+「校验前置」。
立即学习“Python免费学习笔记(深入)”;
- 合并前先按
chunkIndex排序,检查是否缺片(set(range(totalChunks)) - set(received_indices)) - 用
shutil.copyfileobj()逐个分片 copy 到目标文件,不加载全文本到内存 - 每写完一片,更新 Redis 中的进度哈希(
redis.hset('upload:{upload_id}', 'chunks_done', len(done_list))) - 合并完成后立刻用
hashlib.md5()校验最终文件 hash,和前端传来的fileHash对不上就删掉重来
断点续传怎么让前端知道“我该从哪继续”
断点续传不是后端记个“已收 37 片”就行——前端需要明确的、可执行的响应,否则它只能重头开始。关键在于返回的 HTTP 状态码和 body 要能被前端 SDK(如 axios 或 uppy)直接解析。
典型错误是返回 200 + {"status": "ok"},前端根本不知道哪些片已存在;或者返回 409 表示冲突,却不带已接收的索引列表。
- 收到分片请求时,先查 Redis 或 DB:是否存在
upload:{upload_id}:chunks这个 set,里面有哪些chunkIndex - 如果该分片已存在,直接返回
200 OK,body 为{"exists": true}(部分 SDK 依赖这个判断跳过) - 提供独立的
GET /api/upload/status?upload_id=xxx接口,返回{"uploaded_chunks": [0,1,3,4], "total_chunks": 10} - 不要在上传接口里做耗时校验(如全量 hash 计算),状态查询必须毫秒级响应
Flask/FastAPI 怎么扛住并发分片请求不丢片
默认 Flask 是同步阻塞模型,FastAPI 默认异步但 DB 操作仍可能阻塞。100 个用户同时上传,每个传 50 片,瞬间几百个请求进来,如果每片都去查一次 Redis + 写一次磁盘,很容易出现超时、连接池打满、甚至分片写一半被中断。
核心不是换框架,而是把「接收」和「落盘」解耦。
- 上传接口只做轻量操作:参数校验 → Redis 记录已收索引 → 返回成功 → 把「合并任务」推入 Celery 或 RQ 队列
- 临时文件统一放在本地 SSD 目录(如
/data/upload_chunks),别放 NFS 或网络盘,IO 延迟会放大并发问题 - 用
flock()或 Redis 分布式锁保护合并动作,防止同一 upload_id 被多个 worker 同时合并 - Nginx 层配置
client_max_body_size 100M和proxy_buffering off,避免缓冲干扰分片边界
真正麻烦的从来不是“怎么拼起来”,而是“怎么确保每一片都稳稳当当落到该去的地方,且前后顺序和完整性可验证”。中间任何一环靠约定、靠运气,上线后就会在凌晨三点给你发告警。










