TP6.0 构建支持断点续传的超大附件上传服务【分片】
在ThinkPHP6.0中实现支持断点续传的超大附件上传,采用分片上传方案。前端按2MB切片并生成唯一chunkId,通过GET请求校验已传分片,用localStorage持久化上传状态。后端控制器接收分片存储,创建upload_status表管理进度,合并时加文件锁并校验MD5,确保生产环境下的可靠性与性能。
先说一个核心判断:在 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,这才是真正持久的方案。
TP6 控制器接收与临时存储
后端处理分片,有两种主流方案。
方案一:用 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'。
这套逻辑跑下来,基本能覆盖生产环境中的绝大多数异常场景。如果后续遇到性能瓶颈,可以考虑在合并时启用异步任务队列,但那是另一个话题了。
Shapr3D是一款面向工业设计、机械工程、建筑概念和三维打印工作流的CAD软件。Mac版采用Parasolid建模内核,支持草图约束、实体建模、工程图、可视化渲染及常见CAD格式交换,并可通过账户在多台设备之间同步项目。
REAPER是Cockos开发的数字音频工作站,提供多轨音频与MIDI录制、剪辑、处理、混音和母带制作工具。Mac版兼容Intel与Apple芯片,支持AU、VST、VST3、CLAP等插件格式,并提供高度可定制的工作流程。
Ableton Live 是面向音乐制作人与现场表演者的数字音频工作站,提供编曲视图、独具特色的现场视图、音频录制、MIDI创作、实时变速、乐器及效果器。Mac版原生支持Apple芯片,并可连接音频接口、MIDI控制器和第三方插件。
Photoshop 2026 是 Adobe 推出的专业图像处理与视觉设计软件,支持 Windows、macOS 和 iPad 等平台,广泛应用于摄影修图、电商设计、平面海报、数字绘画及视觉合成等创作场景。
Blender 是一款免费开源、跨平台的专业 3D 创作软件,集建模、动画、渲染、视频编辑与视觉合成等功能于一体,广泛应用于影视动画、游戏设计和建筑可视化等领域。软件支持 Cycles 物理渲染器与 Eevee 实时渲染引擎,并提供多边形建模、骨骼绑定、物理模拟等专业工具。Blender 兼容 Windows、macOS 和 Linux 系统,安装包轻巧、运行流畅,依托活跃的全球开发者社区持续更新,是从初学者到专业创作者都值得选择的正版 3D 创作工具。














