IT俱乐部 PHP PHP实现大文件分片上传的完整代码

PHP实现大文件分片上传的完整代码

实战干货:原生PHP实现大文件分片上传,无需框架、开箱即用,支持普通大文件上传,完美解决PHP大文件上传超时、内存溢出、表单限制等核心问题,适配服务器生产环境。

在日常开发中,直接使用PHP原生上传接口传输几百MB甚至几GB的大文件,会遇到诸多致命问题:

  • PHP脚本执行超时(max_execution_time 限制)
  • 服务器POST数据大小、单文件上传大小限制
  • 一次性读取大文件导致内存溢出
  • 上传中断需要重新上传,不支持断点续传

分片上传是解决以上问题的最优方案,本文将从零实现一套 前端分片切割 + PHP后端接收合并 的完整上传方案,代码简洁、可直接部署使用。

一、分片上传核心原理

分片上传的核心思想:化整为零,分批传输,最后合并,具体流程如下:

  1. 前端切片:通过JS File API 将超大文件切割为固定大小的小分片(1MB~5MB)
  2. 唯一标识:对原文件生成MD5唯一指纹,区分不同文件的分片,避免冲突
  3. 逐片上传:异步批量上传每一个分片,携带分片索引、总分片数等参数
  4. 后端暂存:PHP接收分片,临时存储在单独目录,按规则命名区分
  5. 合并文件:所有分片上传完成后,后端按索引顺序合并所有分片,生成完整文件
  6. 清理缓存:合并完成后自动删除临时分片文件,释放服务器存储空间

二、环境前置配置(必改)

PHP默认配置严格限制文件上传,必须修改 php.ini 配置文件,否则分片上传会失效。

修改 php.ini 核心参数

; 单文件最大上传大小(根据业务调整)
upload_max_filesize = 100M
; POST请求最大数据大小
post_max_size = 100M
; 脚本执行时间 0=不限制
max_execution_time = 0
; 脚本内存限制,大文件上传建议调高
memory_limit = 512M
; 关闭文件上传临时文件清理(可选)
upload_tmp_dir = /tmp

修改完成后,重启Apache/Nginx、PHP-FPM 服务生效。

三、完整代码实现

整套方案分为 前端上传页面(index.html) 和 PHP后端接收接口(upload.php),两个文件放在同一目录即可运行。

前端页面:文件切片+异步上传

实现文件选择、自动切片、进度条展示、逐片异步上传功能,原生JS无依赖。



    PHP大文件分片上传
        .box{margin: 50px auto;width: 400px;}
        .progress{width: 100%;height: 12px;background: #eee;border-radius: 6px;margin: 15px 0;overflow: hidden;}
        .progress-bar{height: 100%;background: #1677ff;width: 0;transition: width 0.3s;}
        .tip{color: #666;margin-top: 10px;}
    

大文件分片上传演示

请选择需要上传的大文件
// 单个分片大小:1MB(可调整2M/5M) const CHUNK_SIZE = 1 * 1024 * 1024; const fileDom = document.getElementById('file'); const progressDom = document.getElementById('progress'); const msgDom = document.getElementById('msg'); // 监听文件选择 fileDom.addEventListener('change', async function (e) { const file = e.target.files[0]; if (!file) return; // 初始化状态 progressDom.style.width = '0%'; msgDom.innerText = '正在解析文件...'; // 生成文件唯一标识(简易MD5,生产建议使用spark-md5) const fileMd5 = await getFileUniqueId(file); // 计算总分片数 const totalChunk = Math.ceil(file.size / CHUNK_SIZE); let successCount = 0; msgDom.innerText = `开始上传,共${totalChunk}个分片`; // 循环上传所有分片 for (let i = 0; i { const xhr = new XMLHttpRequest(); xhr.open('POST', 'upload.php', true); xhr.onload = function () { resolve(JSON.parse(xhr.responseText)); }; xhr.onerror = function () { resolve({code: 1, msg: '请求异常'}); }; xhr.send(data); }); } // 生成文件唯一标识(简易版) function getFileUniqueId(file) { return new Promise(resolve => { const reader = new FileReader(); reader.readAsArrayBuffer(file); reader.onload = function (e) { // 简易唯一ID,生产环境替换为完整MD5 resolve(btoa(e.target.result.slice(0, 100))); }; }); }

后端接口:接收分片+合并文件

PHP核心接口,实现分片接收、临时存储、自动合并、缓存清理全逻辑。

 './uploads/',  // 最终文件保存目录
    'chunk_path'  => './chunks/',   // 分片临时存储目录
];
// 初始化目录
!is_dir($config['upload_path']) && mkdir($config['upload_path'], 0777, true);
!is_dir($config['chunk_path'])  && mkdir($config['chunk_path'], 0777, true);
// 接收前端参数
$index    = intval($_POST['index']);     // 当前分片索引
$total    = intval($_POST['total']);     // 总分片数
$file_md5 = trim($_POST['md5']);         // 文件唯一标识
$filename = trim($_POST['filename']);    // 原始文件名
$chunk    = $_FILES['chunk'];            // 分片文件
// 分片保存路径:md5_索引 命名,防止文件冲突
$chunk_file = $config['chunk_path'] . $file_md5 . '_' . $index;
// 移动分片文件到临时目录
if (!move_uploaded_file($chunk['tmp_name'], $chunk_file)) {
    exit(json_encode(['code' => 1, 'msg' => '分片上传失败']));
}
// 所有分片上传完毕,执行文件合并
if ($index == $total - 1) {
    // 拼接最终文件路径
    $final_file = $config['upload_path'] . $filename;
    // 二进制方式创建文件
    $handle = fopen($final_file, 'wb');
    // 按顺序读取分片并写入最终文件
    for ($i = 0; $i  0, 'msg' => 'success']);
?>

四、项目目录结构

部署后自动生成目录,无需手动创建,结构清晰:

项目根目录
├── index.html      # 前端上传页面
├── upload.php      # 后端接收合并接口
├── uploads/        # 最终上传文件存储目录(自动生成)
└── chunks/         # 分片临时缓存目录(自动生成)

五、核心知识点解析

分片大小选择

  • 推荐区间:1MB – 5MB
  • 分片过小:请求次数过多,占用服务器HTTP资源,上传变慢
  • 分片过大:单请求超时概率高,失去分片意义

分片命名规则

采用 文件MD5_分片索引 命名,完美解决:

  • 多文件同时上传的分片冲突问题
  • 分片顺序错乱导致文件损坏问题

二进制合并原理

使用 fopen(xx,wb) 二进制覆写模式,逐片拼接文件二进制流,不改变文件编码、格式,支持视频、压缩包、图片、文档等所有文件格式。

六、生产环境进阶优化(必备)

上述代码为基础可用版本,生产环境需优化以下功能,提升稳定性和安全性:

实现断点续传

新增 查询已上传分片接口,上传前请求后端,获取当前文件已上传的分片索引,跳过已上传分片,中断后无需重传全部文件。

完善安全校验

  • 限制上传文件后缀,禁止php、exe、sh等恶意文件
  • 文件合并后校验整体MD5,防止文件损坏、篡改
  • 增加请求token验证,防止恶意刷接口

异常容错处理

  • 前端增加分片失败自动重试机制
  • 后端增加分片过期清理脚本,定时删除残留缓存分片
  • 增加文件大小、分片数量合法性校验

性能优化

  • 前端开启并发上传(同时上传2-3个分片),提升上传速度
  • 后端使用文件指针流式合并,替代file_get_contents,降低大文件内存占用

七、常见问题避坑指南

  • 上传超时:务必设置 max_execution_time=0,关闭脚本执行时间限制
  • 文件合并损坏:必须按分片索引顺序合并,不可无序拼接
  • 权限报错:给项目目录设置 0777 权限,保证PHP有读写、创建、删除权限
  • 分片残留:服务器定时清理 chunks 临时目录,避免磁盘占用过高
  • 大文件内存溢出:调高 memory_limit,优先使用流式读写

八、总结

PHP大文件分片上传的核心逻辑就是 前端切片、后端暂存、最终合并。本文提供的源码无框架依赖、轻量化、可直接部署,彻底解决了传统PHP单文件上传的各类限制问题。

基础版本可满足中小型项目需求,搭配断点续传、安全校验、定时清理等进阶功能后,可直接用于企业级生产环境。

以上就是PHP实现大文件分片上传的完整代码的详细内容,更多关于PHP大文件分片上传的资料请关注IT俱乐部其它相关文章!

本文收集自网络,不代表IT俱乐部立场,转载请注明出处。https://www.2it.club/code/php/18726.html
上一篇
下一篇
联系我们

联系我们

在线咨询: QQ交谈

邮箱: 1120393934@qq.com

工作时间:周一至周五,9:00-17:30,节假日休息

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部