news 2026/4/17 21:01:13

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/18 7:38:41

《解忧杂货店》图书介绍

《解忧杂货店》图书介绍 《解忧杂货店》是日本知名作家东野圭吾的经典长篇小说&#xff0c;也是其创作生涯中极具突破性的作品——它跳出了东野圭吾一贯擅长的推理悬疑框架&#xff0c;以奇幻温情的叙事&#xff0c;成为治愈全球无数读者的心灵之作。该书原作名《ナミヤ雑貨店…

作者头像 李华
网站建设 2026/3/21 14:20:53

模型微调十年演进

模型微调&#xff08;Fine-tuning&#xff09; 的十年&#xff08;2015–2025&#xff09;&#xff0c;是从“全量参数重训”向“极低成本适配”&#xff0c;再到“价值观深度对齐”的进化史。 这十年中&#xff0c;微调技术完成了从学术实验室的昂贵消耗品到开发者手中的即插即…

作者头像 李华
网站建设 2026/4/17 6:10:14

有效利用长尾关键词提升SEO表现及搜索引擎流量的策略

长尾关键词在提升SEO效果和搜索引擎流量方面具有显著的优势。这类关键词由于竞争较小&#xff0c;常常能够为网站带来更精准的流量。本文将详细探讨如何利用长尾关键词进行有效的关键词优化。一方面&#xff0c;长尾关键词能够帮助网站更好地匹配用户的搜索意图&#xff0c;提供…

作者头像 李华
网站建设 2026/4/8 18:39:26

从入门到精通:大模型微调实战全攻略

在人工智能领域&#xff0c;大语言模型已经展现出了令人惊叹的语言理解和生成能力。然而&#xff0c;对于许多企业和开发者而言&#xff0c;直接使用这些通用模型往往难以满足特定的业务需求。医疗AI需要理解专业的医学术语&#xff0c;客服机器人需要掌握特定的话术规范&#…

作者头像 李华
网站建设 2026/4/17 18:32:39

CANN异构架构:以ops-nn为翼,驱动AIGC底层计算新突破

CANN异构架构&#xff1a;以ops-nn为翼&#xff0c;驱动AIGC底层计算新突破 AIGC技术的产业化落地&#xff0c;核心在于底层计算架构对算法的高效支撑&#xff0c;而华为CANN&#xff08;Compute Architecture for Neural Networks&#xff09;作为面向AI场景打造的异构计算架…

作者头像 李华