news 2026/4/23 16:16:35

PHP如何实现500M以上大文件上传的解决方案?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PHP如何实现500M以上大文件上传的解决方案?

开发者日记:2023年X月X日 星期X 武汉 阴

项目背景
今日正式启动客户的大文件传输系统项目,需求明确:支持20G文件/文件夹上传下载、跨平台(Windows/macOS/Linux)、全浏览器兼容(含IE8)、断点续传、保留文件夹层级结构。后端使用PHP + MySQL,存储用阿里云OSS,前端为Vue3 CLI + WebUploader/H5。客户强调高频文件夹上传场景,需极致优化用户体验。免费开源代码和7*24支持的压力依旧,但技术栈熟悉度较高,信心渐增。


技术选型与调整

  1. 前端框架

    • Vue3 CLI:组件化开发,配合@babel/polyfill兼容IE8。
    • WebUploader:核心上传组件,深度定制文件夹解析逻辑。
    • H5 File API:现代浏览器备用方案,IE8回退到Flash上传。
  2. 后端架构

    • PHP 8.1:处理分片上传、MySQL元数据存储、OSS直传。
    • MySQL 8.0:存储文件路径、分片状态、用户ID(InnoDB引擎保证事务)。
  3. 核心难点

    • 高频文件夹上传:优化递归解析性能,避免前端卡顿。
    • 断点续传稳定性:MySQL事务保证分片记录一致性。
    • IE8兼容性:Flash上传需处理跨域问题(crossdomain.xml)。

前端代码实现(Vue3 + WebUploader)

1. 文件夹上传组件
// src/components/FolderUploader.vueimport{ref,onMounted}from'vue';importWebUploaderfrom'webuploader';import'webuploader/dist/webuploader.css';exportdefault{setup(){constuploader=ref(null);constfolderTree=ref([]);onMounted(()=>{// 动态加载Flash(IE8兼容)if(!WebUploader.Uploader.support('HTML5')){WebUploader.Uploader.register({name:'flash',fn:()=>'/assets/Uploader.swf'});}uploader.value=newWebUploader.Uploader({swf:'/assets/Uploader.swf',server:'/api/upload.php',chunked:true,chunkSize:4*1024*1024,// 4MB分片formData:{fileId:'',relativePath:''// 关键:记录文件相对路径}});});consttriggerFolderInput=()=>{document.getElementById('folderInput').click();};// 递归解析文件夹(兼容现代浏览器)consthandleFolderSelect=(e)=>{constitems=e.target.files;if(items){consttree=[];for(leti=0;i<items.length;i++){constfile=items[i];constpath=file.webkitRelativePath||file.name;// 相对路径constsegments=path.split('/');// 构建树形结构letcurrentLevel=tree;segments.slice(0,-1).forEach(segment=>{letdir=currentLevel.find(item=>item.name===segment);if(!dir){dir={name:segment,type:'directory',children:[]};currentLevel.push(dir);}currentLevel=dir.children;});// 添加文件节点currentLevel.push({name:segments.pop(),type:'file',file:file,relativePath:path});}folderTree.value=tree;uploadFolder(tree);}};// 上传文件夹内容constuploadFolder=(tree)=>{tree.forEach(node=>{if(node.type==='directory'){uploadFolder(node.children);// 递归上传子目录}else{constformData=uploader.value.option('formData');formData.relativePath=node.relativePath;uploader.value.addFile(node.file,node.relativePath);}});uploader.value.upload();// 触发上传};return{triggerFolderInput,folderTree};}};
2. IE8兼容性处理

后端代码实现(PHP + MySQL)

1. 分片上传接口
setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);$stmt=$pdo->prepare(" INSERT INTO upload_progress (file_id, chunk_index, total_chunks, uploaded_at) VALUES (?, ?, ?, NOW()) ON DUPLICATE KEY UPDATE updated_at = NOW() ");$stmt->execute([$fileId,$chunkIndex,$totalChunks]);// 如果是最后一块,合并并上传OSSif($chunkIndex===$totalChunks-1){$finalPath="{$tempDir}/final_file";$fp=fopen($finalPath,'wb');for($i=0;$i<$totalChunks;$i++){$chunk=file_get_contents("{$tempDir}/chunk_{$i}");fwrite($fp,$chunk);}fclose($fp);// 上传OSS(需引入阿里云OSS SDK)require_once'oss-sdk/autoload.php';$ossClient=newOSS\OssClient($OSS_KEY,$OSS_SECRET,$OSS_ENDPOINT);$ossClient->putObject($OSS_BUCKET,"uploads/{$fileId}",$finalPath);// 清理临时文件array_map('unlink',glob("{$tempDir}/*"));rmdir($tempDir);// 保存文件元数据到MySQL$metaStmt=$pdo->prepare(" INSERT INTO file_metadata (file_id, relative_path, size, uploaded_at) VALUES (?, ?, ?, NOW()) ");$metaStmt->execute([$fileId,$relativePath,filesize($finalPath)]);}echojson_encode(['success'=>true,'fileId'=>$fileId]);}catch(Exception$e){http_response_code(500);echojson_encode(['error'=>$e->getMessage()]);}?>
2. MySQL表结构
-- 文件分片进度表CREATETABLE`upload_progress`(`id`int(11)NOTNULLAUTO_INCREMENT,`file_id`varchar(64)NOTNULLCOMMENT'文件唯一ID',`chunk_index`int(11)NOTNULLCOMMENT'分片索引',`total_chunks`int(11)NOTNULLCOMMENT'总分片数',`uploaded_at`datetimeNOTNULLDEFAULTCURRENT_TIMESTAMP,`updated_at`datetimeNOTNULLDEFAULTCURRENT_TIMESTAMPONUPDATECURRENT_TIMESTAMP,PRIMARYKEY(`id`),UNIQUEKEY`idx_file_chunk`(`file_id`,`chunk_index`))ENGINE=InnoDBDEFAULTCHARSET=utf8mb4;-- 文件元数据表CREATETABLE`file_metadata`(`id`int(11)NOTNULLAUTO_INCREMENT,`file_id`varchar(64)NOTNULLCOMMENT'文件唯一ID',`relative_path`varchar(512)NOTNULLCOMMENT'文件相对路径',`size`bigint(20)NOTNULLCOMMENT'文件大小(字节)',`uploaded_at`datetimeNOTNULLDEFAULTCURRENT_TIMESTAMP,PRIMARYKEY(`id`),UNIQUEKEY`idx_file_path`(`file_id`,`relative_path`))ENGINE=InnoDBDEFAULTCHARSET=utf8mb4;

断点续传实现

1. 前端恢复逻辑
// 检查未完成上传constcheckResume=async(fileId)=>{constres=awaitfetch(`/api/progress.php?fileId=${fileId}`);constdata=awaitres.json();if(data.completedChunks<data.totalChunks){uploader.value.option('formData',{fileId,chunk:data.completedChunks});uploader.value.upload();}};// 本地存储fileId(即使浏览器关闭)window.addEventListener('beforeunload',()=>{if(uploader.value.getFiles().length>0){localStorage.setItem('lastUploadId',uploader.value.option('formData').fileId);}});
2. 后端进度查询
'fileId is required']);exit;}try{$pdo=newPDO("mysql:host={$DB_HOST};dbname={$DB_NAME}",$DB_USER,$DB_PASS);$stmt=$pdo->prepare(" SELECT COUNT(*) AS completed, MAX(total_chunks) AS total FROM upload_progress WHERE file_id = ? ");$stmt->execute([$fileId]);$result=$stmt->fetch(PDO::FETCH_ASSOC);echojson_encode(['completedChunks'=>(int)$result['completed'],'totalChunks'=>(int)$result['total']]);}catch(Exception$e){http_response_code(500);echojson_encode(['error'=>$e->getMessage()]);}?>

今日总结

  • 进展:完成文件夹层级解析和PHP分片上传逻辑,IE8兼容性方案验证通过。
  • 问题
    1. WebUploader在IE8下对大文件夹性能较差,需优化DOM操作。
    2. MySQL事务需加强,避免分片记录残留。
  • 明日计划
    1. 实现OSS分片上传(避免本地合并临时文件)。
    2. 编写完整的开发文档和API接口说明。

求助:若有熟悉PHP文件处理或MySQL优化的高手,欢迎加入QQ群374992201指导!代码将完全开源回馈社区。


(注:实际项目需补充安全校验、OSS直传和性能监控代码。)

安装环境

PHP:7.2.14

调整块大小

NOSQL

NOSQL不需要任何配置,可以直接访问测试

SQL

创建数据库

您可以直接复制脚本进行创建

配置数据库连接

安装依赖

访问页面进行测试

数据表中的数据

效果预览

文件上传

文件刷新续传

支持离线保存文件进度,在关闭浏览器,刷新浏览器后进行不丢失,仍然能够继续上传

文件夹上传

支持上传文件夹并保留层级结构,同样支持进度信息离线保存,刷新页面,关闭页面,重启系统不丢失上传进度。

批量下载

支持文件批量下载

下载续传

文件下载支持离线保存进度信息,刷新页面,关闭页面,重启系统均不会丢失进度信息。

文件夹下载

支持下载文件夹,并保留层级结构,不打包,不占用服务器资源。

免费下载示例

点击下载完整示例

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 11:12:51

定稿前必看!9个AI论文工具:研究生毕业论文写作全维度测评

随着人工智能技术的不断进步&#xff0c;学术写作正迎来一场深刻的变革。对于研究生群体而言&#xff0c;从选题构思到文献综述、从初稿撰写到格式调整&#xff0c;每一个环节都可能成为耗时耗力的“重灾区”。而AI工具的出现&#xff0c;为这一过程带来了全新的解决方案。为了…

作者头像 李华
网站建设 2026/4/23 12:14:27

中专学财务,2026年就业方向全解析:从出纳到财务BP的进阶路

中专学财务2026年就业方向解析2026年财务领域的就业方向呈现多元化趋势&#xff0c;中专学历的财务从业者可通过考取CDA数据分析师证书等专业资质&#xff0c;提升竞争力。以下是详细职业路径分析及对应能力要求。基础岗位&#xff1a;出纳/会计助理适合初入行业的从业者&#…

作者头像 李华
网站建设 2026/4/23 10:38:30

对比一圈后!专科生必备的AI论文写作神器 —— 千笔AI

你是否曾为论文的选题而发愁&#xff1f;是否在写到一半时突然卡壳&#xff0c;不知如何继续&#xff1f;又或者反复修改后仍对结果不满意&#xff1f;对于专科生来说&#xff0c;论文写作不仅是学业的一部分&#xff0c;更是一场与时间、压力和自我怀疑的较量。面对文献查找困…

作者头像 李华
网站建设 2026/4/23 12:16:27

java+vue基于springboot框架的WeJob求职招聘网站

目录WeJob求职招聘网站摘要开发技术源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;WeJob求职招聘网站摘要 技术架构 采用SpringBoot作为后端框架&#xff0c;Vue.js作为前端框架&#xff0c;实现前后端分离开发。后端使用MyBatis或JPA…

作者头像 李华