发布于2026-07-15 阅读(0)
扫一扫,手机访问
先说一个核心判断:在 ThinkPHP 6.0 里做超大附件上传,如果只想跑通 Demo,那随便找个插件就能糊弄过去。但真要拿到生产环境去扛 10GB 的视频、5 万个小文件,还要兼容 IE11 和 Chrome、Firefox 的混合访问,那就不是拼凑代码能解决的事了。
这篇内容不聊花架子,直接拆解一套能落地的方案:分片上传、断点续传、多文件并发、刷新页面后进度不丢——每一项都是实战中踩过坑才摸清楚的门道。

先说说前端这块。用 File API 读取文件,按 2MB 切片——注意,切片的尺寸必须和后端配置严格一致,不然合并的时候会校验失败,到时候排查起来够你头疼的。
每个分片都需要一个唯一的 chunkId。推荐的做法是用 file.name + file.lastModified + sliceIndex 拼一个 MD5,这个 ID 会贯穿整个上传生命周期。注意,不可重复,不可随机生成,否则断点续传的逻辑会乱掉。
上传前的校验步骤很关键:先发一个 GET 请求到 /api/upload/check?chunkId=xxx&chunkIndex=0,问一下这个分片是不是已经存在。如果服务端返回 200,说明已经存过了,直接跳过;返回 404,再执行 POST 上传。这一步能省掉大量的重复传输,也是断点恢复的基石。
分片上传成功后,立刻调用 localStorage.setItem('upload_' + chunkId, JSON.stringify(...)) 把状态存下来。这里有个常见错误:有人为了省事用 sessionStorage,结果页面一刷新,数据全清空,断点续传直接废掉。必须用 localStorage,这才是真正持久的方案。
后端处理分片,有两种主流方案。
方案一:用 request()->file() 直接接收
在 app/controller/Upload.php 里定义 uploadChunk 方法,接收 chunkid、chunkindex、chunkcount、filename 这些参数。务必校验 chunkindex 是数字且大于等于 0,这一步是为了防止路径穿越攻击,别在这种地方翻车。
方案二:手动读取原始流
如果遇到超大分片,或者 Nginx 配置有局限,request()->file() 可能绕不过去。这时候改用 file_get_contents('php://input') 直接拿原始二进制流,再用 file_put_contents 写入临时目录。这个方案绕过了 TP6 的自带文件校验,所以你得自己做好 MIME 类型白名单过滤,否则就是安全隐患。
所有分片统一存到 runtime/upload/chunks/{date}/{chunkid}/ 目录下,文件名格式为 {chunkid}-{chunkindex}.tmp。日期子目录的作用很实际:防止单目录下文件过多导致 Linux ext4 文件系统性能下降。
前端的状态管理搞定之后,服务端也得有一套完整的追踪机制。
首先,创建一张 upload_status 表,字段包括 id、chunkid、total_chunks、uploaded_count、status(取值 'uploading'、'completed'、'failed')、updated_time。主键设为 chunkid,避免重复插入。
每次分片上传成功后,执行 INSERT ... ON DUPLICATE KEY UPDATE 语句来更新 uploaded_count,同时记录 updated_time。这个操作是原子性的,不用担心并发导致计数错乱。
用户刷新页面后,前端调用 /api/upload/status?chunkid=xxx,后端从 upload_status 表查当前已上传的分片索引数组,前端据此跳过已传的,从第一个缺失的索引继续上传。
容错处理也很重要:如果某个分片连续 3 次上传失败(HTTP 500 或超时),就把 status 置为 'failed',并记录错误码。前端收到后弹窗提示“第 X 块上传失败,请检查网络”,但不自动重试——避免死循环把磁盘刷爆。
当最后一个分片(chunkindex == chunkcount - 1)上传完成,就会触发合并流程。这一步最考验严谨性。
具体步骤如下:
① 先用 flock 加写锁。这一步是为了防止多个请求同时合并同一个文件,避免数据错乱。
② 遍历检查所有分片文件是否存在,且大小是否正确——每个分片大约 2MB,最后一片可能略小,这是正常情况。
③ 按 chunkindex 升序,逐个 fopen → fread → fwrite 追加到目标文件。
④ 合并完成后,计算最终文件的 MD5,与前端传来的 fileMd5 比对。如果不一致,立刻 unlink 目标文件并报错。
⑤ 成功后,清理所有 .tmp 分片文件,并将 upload_status.status 更新为 'completed'。
这套逻辑跑下来,基本能覆盖生产环境中的绝大多数异常场景。如果后续遇到性能瓶颈,可以考虑在合并时启用异步任务队列,但那是另一个话题了。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8