thinkphp大文件上传必须分片处理,核心是前后端切片规则对齐、状态可追溯、失败可恢复;需基于文件名、最后修改时间、大小生成稳定chunkid,服务端校验分片存在性并存临时文件,合并前加锁校验md5一致性,同时调优php、nginx及中间件配置。

ThinkPHP项目做大文件上传,分片处理不是可选项,而是生产环境的底线要求。核心在于前后端严格对齐切片规则、状态可追溯、失败可恢复——不是把文件切开再拼回去那么简单。
前端切片与唯一标识生成
用File API或WebUploader等成熟库切片,固定chunkSize(如2MB),必须与后端配置完全一致。切片时不要用随机ID,而是基于文件元信息生成稳定唯一chunkId:推荐file.name + file.lastModified + file.size三者拼接后取MD5。这个ID将用于校验、去重、状态查询和本地缓存,贯穿整个生命周期。
每次上传前先GET请求/api/upload/check?chunkId=xxx&chunkIndex=n,服务端查该分片是否已存在;存在则跳过,不存在才POST上传。上传成功后立即写入localStorage:localStorage.setItem('upload_' + chunkId, JSON.stringify({index: n, status: 'success'}))。别用sessionStorage,刷新即丢进度。
后端接收与临时存储规范
在控制器中定义uploadChunk方法,接收chunkId、chunkIndex、chunkCount、filename等参数。务必校验chunkIndex为非负整数,防止路径穿越。
分片统一存到runtime/chunks/{date}/{chunkId}/目录下,文件名格式为{chunkId}-{chunkIndex}.tmp。按日期分目录可避免单目录海量小文件导致Linux ext4性能下降。若遇到Nginx限制或超大分片,可改用file_get_contents('php://input')读原始流,但需自行做MIME白名单过滤。
状态跟踪与合并保障
建upload_status表,字段包括chunkid、total_chunks、uploaded_count、status、updated_time。每次分片上传成功,执行INSERT ... ON DUPLICATE KEY UPDATE更新计数和时间戳。
所有分片传完后触发合并:先加行锁查uploaded_count == total_chunks,再按序读取各.tmp文件,用fopen(..., 'ab')追加写入目标文件,最后校验合并后文件的MD5是否与前端预计算一致。不一致则标记失败并清理临时数据。
底层配置必须同步调优
光写逻辑没用,PHP和Nginx会提前拦截:
-
PHP层:
upload_max_filesize和post_max_size必须同步调大(如64M / 72M),改完重启php-fpm,并用phpinfo()确认生效 -
Nginx层:在server块内设
client_max_body_size 100M,同时调大client_body_timeout 300和fastcgi_read_timeout 300 - 中间件:反向代理、CDN、WAF常自带body size限制,必须一并检查
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











