thinkphp原生上传不支持断点续传,须改用前后端分片方案:前端切片+计算md5指纹+状态管理,后端独立接口处理分片上传与合并,并配置php/nginx参数避免拦截。

ThinkPHP 原生的文件上传机制(如 request()->file() 或 Upload 类)不支持断点续传。它依赖 PHP 的 $_FILES 同步接收模型,只能处理一次完整上传,无法应对网络中断、大文件分片、服务端状态恢复等场景。要真正支持断点续传,必须放弃表单直传方式,改用前后端协同的分片上传方案。
前端必须自主切片并管理上传状态
不能用普通 <form enctype="multipart/form-data"></form> 提交,而要用 JavaScript(File API + fetch/Axios)控制全流程:
- 用
file.slice(start, end)按固定大小(如 5MB)切片 - 计算全文件指纹(推荐
spark-md5算 MD5),作为唯一标识fileFingerprint - 每个分片请求携带:
fileFingerprint、chunkIndex、totalChunks、fileName - 上传前先调接口查已传分片,跳过已成功部分,实现“断点”识别
后端需绕过 Upload 类,直连分片逻辑
TP5/TP6 都不可复用 Upload 或 request()->file()——它们在分片场景下会返回 null 或报错。正确做法是:
- 定义独立接口:如
/upload/init(初始化)、/upload/chunk(上传分片)、/upload/complete(合并) - 用
input('param.chunk')、input('param.chunks')等获取分片参数,而非request()->file() - 分片文件保存为临时命名(如
{md5}_{index}.part),存入public/uploads/chunks/等可写目录 - 记录上传进度到数据库或 Redis(如
upload_status表含chunkid、uploaded_count、status)
合并时校验完整性,避免损坏
最后一个分片上传后,触发合并操作,关键步骤包括:
- 检查该
fileFingerprint对应的所有分片是否全部存在且大小匹配 - 用
fopen(..., 'ab')追加写入,避免内存溢出(不用file_get_contents) - 合并完成后计算最终文件 MD5,与原始指纹比对,不一致则拒绝并清空临时分片
- 成功后删除所有
.part文件,返回可访问的 URL(如/uploads/202610/abc123.mp4)
注意环境与配置限制
即使逻辑写对,以下配置错误也会导致上传失败或无法断点:
- PHP 配置:确保
file_uploads = On,upload_max_filesize和post_max_size足够大(如1024M),且后者 ≥ 前者 - Nginx 配置:添加
client_max_body_size 1024m;,否则单个分片请求可能被拦截 - ThinkPHP 验证规则(如
'size:2048')只作用于已接收到的文件,不解决“根本没收到”的问题,调试时先dump($_FILES)确认原始数据
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











