分片上传通过将大文件切分为小块并独立传输实现高效可靠上传。前端按固定大小切片并计算唯一chunkHash,后端暂存为.part文件;支持断点续传、失败重试、流式合并与完整性校验。

分片上传:把大文件切成小块再传
直接上传几GB的文件容易超时或被服务器拒绝。分片的核心思路是:前端用 JavaScript 把文件按固定大小(比如 2MB/片)切开,每片单独发请求,后端接收后暂存为临时分片文件,不合并,只记录信息。
关键点:
- 前端需计算每片的唯一标识,常用 文件名 + 文件总大小 + 当前分片序号 + 分片大小 做 hash(如 md5),避免重名冲突
- 上传时携带参数:
filename、totalSize、chunkIndex、totalChunks、chunkHash - 后端 PHP 接收后,把分片存到统一目录(如
uploads/chunks/),文件名建议用{chunkHash}.part - 不要在每次上传分片时校验整个文件 hash——太慢;可在所有分片上传完后再对全部分片拼接校验
断点续传:上传中断后知道从哪继续
用户刷新页面、网络闪断、浏览器崩溃,都不该让之前传过的分片白费。实现依赖服务端“已传分片清单”查询接口。
操作流程:
立即学习“PHP免费学习笔记(深入)”;
- 文件选中后,前端先发一个
GET /api/upload/status?filename=xxx&totalSize=yyy请求 - 后端根据 filename 和 totalSize 查数据库或扫描
chunks/目录,返回已上传的chunkIndex数组(如[0,1,2,4,5]) - 前端跳过这些索引,只上传缺失的分片(如 3、6、7…)
- 注意:不同设备/浏览器视为独立上传会话,如需跨端续传,需额外引入用户身份或上传任务 ID
失败重试:自动补传出错的分片
单个分片上传可能因网络抖动、502、超时等失败。不能整批重来,而要精准重试失败项。
建议做法:
- 前端对每个分片上传使用
fetch或axios,设置合理 timeout(如 30s),捕获 reject 并记录失败 index - 失败后延迟 1–3 秒再重试,最多 3 次;第 3 次仍失败则标记为“不可恢复”,暂停上传并提示用户
- 后端 PHP 不需要特殊处理重试逻辑,只要保证同一
chunkHash的多次上传是幂等的(重复写入同名 .part 文件即可) - 可加简单防刷:同一个 IP 对同一文件 1 分钟内对同一分片的请求超过 5 次,返回 429
合并与校验:所有分片齐了才生成最终文件
当后端收到 POST /api/upload/merge 请求(含 filename、totalSize、totalChunks),说明前端确认全部分片已就位。
PHP 合并步骤:
- 校验是否所有分片文件都存在(检查
0.part到(n-1).part) - 按序号升序读取每个 .part 文件,用
fopen(..., 'rb')+fwrite流式写入目标文件(避免内存爆炸) - 合并完成后,计算最终文件的 md5/sha256,与前端传来的
fileHash对比(如有) - 校验通过则删除所有 .part 文件,返回成功;失败则保留分片,返回错误并记录日志
- 加锁机制可选:用
flock()防止并发合并同一文件,或用 Redis 锁控制任务唯一性
不复杂但容易忽略细节,稳住分片、状态、校验三环,大文件上传就能既快又可靠。



















