Flask识别同一文件的多个chunk关键在于客户端携带一致的upload_id或file_md5,服务端据此聚合;需校验upload_id合法性、隔离存储、记录接收状态,并通过Redis+本地文件双校验保障一致性。

Flask 接收分块上传时如何识别同一文件的多个 chunk
关键在于客户端必须在每次请求中携带一致的文件标识(如 upload_id 或 file_md5),服务端靠它聚合 chunk。不能只依赖文件名,因为重名或并发上传会冲突。
推荐做法是:前端生成唯一 upload_id(如 UUID),所有该文件的 chunk 都带上这个 ID;后端用它作为临时目录名或 Redis key 存储已接收的 chunk 列表。
- 避免用
request.files['file'].filename做判断——浏览器可能改名,且不可靠 - 务必校验
upload_id是否为合法 UUID 或 16+ 字符哈希,防路径遍历(如传../etc/passwd) - 建议搭配
Content-Rangeheader(如bytes 0-999999/10485760)解析偏移量,比纯序号更健壮
怎么安全地拼接 chunk 并防止磁盘爆满
不要等所有 chunk 收完再合并——万一最后几个丢包,前面几百 MB 就白占着磁盘。应该边收边写入临时文件,并记录每个 chunk 的接收状态。
典型流程:收到 chunk 后,以 upload_id/chunk_{index} 形式存到隔离目录(如 /tmp/uploads/{upload_id}/),同时用 Redis 记录 {upload_id}: {total_chunks: 5, received: [0,1,3]}。合并前先检查是否齐备。
立即学习“Python免费学习笔记(深入)”;
- 临时目录必须设权限(
chmod 700),且挂载点需有足够空间(建议单独挂载/tmp/uploads) - 每个 chunk 写入前做大小限制(如单 chunk ≤ 10MB),用
request.content_length拦截超大请求 - 设置 Redis key 过期时间(如
EXPIRE upload:{id} 3600),避免死数据堆积
断点续传时 Flask 怎么返回已上传的 chunk 列表
客户端发起 GET 请求(如 /api/upload/status?upload_id=abc123),后端查 Redis 或数据库,返回已接收的 chunk 索引数组。这是断点续传的核心响应。
注意:不要返回完整路径或服务器内部结构,只返回客户端能理解的逻辑索引(如 [0,1,3]),由前端决定重传哪些 chunk。
- 响应格式建议用 JSON:
{"uploaded_chunks": [0,1,3], "total_chunks": 5, "chunk_size": 1048576} - 必须校验
upload_id是否存在且未过期,不存在则返回404,而非空列表(否则前端误以为已传完) - 避免在响应里暴露文件真实大小或 MD5——这些应由前端计算并传入,服务端只做校验
合并完成后的文件怎么避免被重复处理或覆盖
合并操作(如 cat chunk_* > final.file)必须是原子的。常见错误是先写入 final.file,再删 chunk 目录——若中途崩溃,会导致残留临时文件和不完整成品。
推荐用临时文件 + 重命名:先写入 final.file.tmp,校验 MD5 合格后,再 os.replace() 覆盖目标文件。同时删除 Redis 中对应 key 和临时目录。
- 合并前务必校验所有 chunk 的 MD5(客户端应随每个 chunk 提交
chunk_md5字段) - 最终文件名不要直接用原始
filename,而用upload_id + secure_filename(ext),防 XSS 或路径注入 - 合并成功后立即清理,但清理失败不能影响业务逻辑——加日志告警,后续用定时任务兜底
实际最难的不是代码,而是 chunk 状态一致性:网络抖动、客户端崩溃、服务重启都可能导致“已上报但未落盘”或“已落盘但未登记”。Redis + 本地文件双校验是目前最稳的组合,但得接受小概率人工介入。


















