php 8.5 不支持断点续传,需自行实现分片上传逻辑:前端切片带 filehash、chunkindex、totalchunks;服务端校验并安全暂存;合并时依赖状态记录而非 glob,且须调大网关超时与体长限制。

PHP 8.5 本身不内置断点续传,得靠你自己搭分片逻辑
PHP 8.5 只是让 move_uploaded_file() 更安全、$_FILES 错误码更细粒度,但它不会自动帮你记哪块传到第几片了。断点续传不是 PHP 版本功能,而是你用 PHP 写出来的业务逻辑——核心就三件事:前端切片、服务端存片、客户端查片再续。
前端切片必须带唯一标识和序号,否则后端根本分不清谁是谁
常见错误是只传 chunk 和 index,但没传文件级唯一 ID。网络重试或用户换设备重传时,不同文件的第 3 片会撞名覆盖。必须加一层稳定哈希,比如:
fileHash = md5(file.name + file.size + (file.lastModified || Date.now()))- 每个请求带
fileHash、chunkIndex、totalChunks三个关键字段 - 别用
Math.random()或时间戳当 ID——重复概率高,合并时会漏片
服务端暂存路径要隔离,不能直接用 $_POST['filename'] 命名
用户改个浏览器开发者工具就能把 filename 改成 ../../etc/passwd,直接写穿目录。正确做法是:
- 临时目录固定为
chunks/,权限设为 750,Web 用户仅可写不可执行 - 文件名强制用
$fileHash . '_' . $chunkIndex,例如ab12cd34_5 - 接收时校验
$chunkIndex是整数、$chunkIndex >= 0、且不超过$totalChunks - 1 - 用
is_uploaded_file($chunk['tmp_name'])判定是否真来自上传,而非伪造路径
合并操作不能靠 glob 猜,得查状态表或原子标记文件
用 count(glob("chunks/{$fileHash}_*")) === $totalChunks 看似简单,但存在竞态:两个请求同时检查、同时合并,可能双写损坏文件。更稳妥的是:
立即学习“PHP免费学习笔记(深入)”;
- 上传每片成功后,往数据库或 Redis 写一条记录:
upload_status:{$fileHash}→["0","2","5"] - 或在
chunks/下写一个标记文件:{$fileHash}.done,仅当所有片落盘且校验通过后再创建它 - 合并时先
fopen($targetFile, 'wb'),再按序fopen($chunkPath, 'rb')+stream_copy_to_stream(),避免内存爆掉 - 合并完立刻
unlink()所有分片,别等 cron 清理——临时文件堆积会吃光磁盘
最易被忽略的一点:HTTP 超时和 Nginx/Apache 的 client_max_body_size、fastcgi_read_timeout 都得同步调大。哪怕 PHP 层逻辑全对,网关层把连接掐了,前端永远收不到“第 17 片 OK”,就会无限重试或卡死。











