分片上传是PHP处理大文件最稳妥的方法:前端按固定大小切片并携带元数据上传,后端逐片接收存储、校验后流式合并,支持断点续传与并发控制。

PHP 本身不支持真正的异步上传,但可以模拟“用户无感”的上传体验
PHP 是同步阻塞式执行的,$_FILES 一读就是整个文件已接收完毕。所谓“异步上传”,实际是前端用 XMLHttpRequest 或 fetch 分片/多请求上传,后端 PHP 配合做分片接收、合并、校验。关键不是让 PHP 异步,而是不让用户卡在上传页面。
用 JavaScript + PHP 实现分片上传(最实用的方案)
这是目前兼容性好、可控性强、能断点续传的主流做法。PHP 端只需处理单个分片的接收与落盘,不需额外扩展。
- 前端按固定大小(如 5MB)切文件,每片带
chunkIndex、totalChunks、identifier(文件唯一 ID) - PHP 接收时检查
$_POST['chunkIndex']和$_POST['identifier'],把分片存到临时目录:upload_tmp/{identifier}/{chunkIndex} - 当收到最后一片(
$_POST['chunkIndex'] == $_POST['totalChunks'] - 1),用file_put_contents()按序合并:foreach (range(0, $total - 1) as $i) { $content .= file_get_contents("upload_tmp/{$id}/{$i}"); } file_put_contents("uploads/{$final_name}", $content); - 务必校验
$_FILES['file']['error'] === UPLOAD_ERR_OK,且限制$_FILES['file']['size']不超过单片上限(防恶意绕过)
为什么不用 move_uploaded_file() 直接处理大文件?
直接传大文件会触发多个 PHP 层级限制,且失败后无法恢复,用户只能重来。
-
upload_max_filesize和post_max_size必须调大,但服务器内存和超时风险同步上升 - Apache/Nginx 默认有
client_max_body_size或LimitRequestBody限制,改配置需重启或权限 - 一旦网络中断或脚本超时(
max_execution_time),整个上传就丢,没有中间状态 - 分片上传可配合
session_write_close()提前释放 session 锁,避免并发上传被阻塞
上传完成后的清理与安全要点
分片临时文件不清理会撑爆磁盘;不校验类型和内容可能执行恶意代码。
立即学习“PHP免费学习笔记(深入)”;
- 合并成功后,用
array_map('unlink', glob("upload_tmp/{$identifier}/*"))清空该文件所有分片 - 不要依赖
$_FILES['file']['type']—— 它只是浏览器传来的 MIME,可伪造;应使用finfo_open(FILEINFO_MIME_TYPE)检查真实类型 - 保存路径必须避开 Web 可访问目录,或用
.htaccess/location ^~ /upload_tmp禁止直接访问 - 最终文件名必须重命名(如
uniqid() . '.' . $ext),不能直接用$_FILES['file']['name']
分片逻辑本身简单,但边界情况多:重复上传同片、乱序到达、某片丢失、identifier 冲突……这些才是上线后真正花时间调试的地方。



















