news 2026/4/16 12:06:09

机械制造行业PHP如何解决500M大文件的上传问题?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
机械制造行业PHP如何解决500M大文件的上传问题?

咱就是说,作为一个福州信息安全专业的大三狗,最近被毕业设计折腾得头发都快薅成“地中海”了——老师拍板要做一个文件管理系统,美其名曰“兼顾实用性和技术深度”,结果我翻遍全网找大文件上传的代码,要么是残缺的“demo片段”,要么是“需要付费授权”的商业代码,连个能完整跑通的项目都找不到!最气的是,遇到问题想找作者问问,要么微信拉黑,要么QQ装死,群里喊破喉咙都没人理……(拍桌)

不过咱是谁?信息安全专业的“卷王”(自封的)!既然网上没现成的,咱就自己造轮子!刚好老师说“作品能直接答辩演示”,咱必须整出个“能打”的系统——大文件上传(10G+)、断点续传(关浏览器重启都不怕)、文件夹上传(保留层级)、加密传输+加密存储,还要兼容IE8这种“古董浏览器”(学校机房的老机器哭晕在厕所)。

先唠唠踩过的坑(血泪史版)

  1. 大文件上传:用WebUploader吧,文档不全;自己用H5 File API?分片、合并、进度保存全得自己写,头秃。
  2. 断点续传:想存进度?localStorage容量不够(10G文件的分片信息得存到后端);关浏览器就丢?那得用IndexedDB或者后端数据库存进度。
  3. 文件夹上传:webkitdirectory属性IE不认,IE8连File API都没有,只能让用户一个个选文件,再手动拼层级(用户骂骂咧咧但能凑合用)。
  4. 加密:传输要HTTPS,存储要AES加密,密钥得存后端(不然被偷库就完犊子)。
  5. 兼容IE8:放弃H5新特性,用iframe模拟异步上传,表单提交……(体验差但能跑)。

甩干货:核心代码(附调试说明)

咱直接上“能跑通”的代码,毕业答辩绝对稳!(PS:部分细节需要根据实际环境调整,群里喊我帮你调~)

前端:Vue3 + 原生JS(大文件分片上传+断点续传)

(兼容IE9+,IE8用iframe fallback,代码里标了注释)

export default { data() { return { uploading: false, progress: 0, chunkSize: 2 * 1024 * 1024, // 分片大小2MB(10G文件分5000片) file: null, fileHash: '', // 文件哈希(用于断点续传标识) uploadedChunks: [] // 已上传的分片序号 }; }, methods: { async handleFileSelect(e) { const files = e.target.files; if (!files.length) return; this.file = files[0]; // 计算文件哈希(用于断点续传,用SparkMD5库) this.fileHash = await this.calculateFileHash(this.file); // 检查后端是否已有部分分片(断点续传关键!) const { data } = await this.$http.get(`/api/checkChunks?hash=${this.fileHash}`); this.uploadedChunks = data.uploadedChunks || []; // 开始上传 this.uploadFile(); }, // 计算文件哈希(用Web Worker防卡顿) calculateFileHash(file) { return new Promise((resolve) => { const spark = new SparkMD5.ArrayBuffer(); const reader = new FileReader(); const chunkSize = this.chunkSize; const chunks = Math.ceil(file.size / chunkSize); let currentChunk = 0; reader.onload = (e) => { spark.append(e.target.result); currentChunk++; if (currentChunk < chunks) { loadNext(); } else { resolve(spark.end()); } }; const loadNext = () => { const start = currentChunk * chunkSize; const end = Math.min(start + chunkSize, file.size); reader.readAsArrayBuffer(file.slice(start, end)); }; loadNext(); }); }, // 上传文件(分片+断点续传) async uploadFile() { this.uploading = true; const totalChunks = Math.ceil(this.file.size / this.chunkSize); for (let i = 0; i < totalChunks; i++) { // 跳过已上传的分片 if (this.uploadedChunks.includes(i)) { this.progress = (i / totalChunks) * 100; continue; } const start = i * this.chunkSize; const end = Math.min(start + this.chunkSize, this.file.size); const chunk = this.file.slice(start, end); // 加密分片(AES加密,密钥从后端获取) const encryptedChunk = await this.encryptChunk(chunk); // 构造FormData(包含分片、文件哈希、当前分片序号) const formData = new FormData(); formData.append('file', encryptedChunk, `${this.fileHash}_${i}`); formData.append('hash', this.fileHash); formData.append('chunkIndex', i); formData.append('totalChunks', totalChunks); try { await this.$http.post('/api/uploadChunk', formData, { headers: { 'Content-Type': 'multipart/form-data' } }); this.uploadedChunks.push(i); this.progress = (i / totalChunks) * 100; } catch (err) { console.error('上传失败:', err); break; } } // 所有分片上传完成,通知后端合并 if (this.uploadedChunks.length === totalChunks) { await this.$http.post('/api/mergeChunks', { hash: this.fileHash, fileName: this.file.name, totalChunks: totalChunks }); alert('上传成功!'); } this.uploading = false; }, // AES加密分片(密钥从后端获取,这里用伪代码) async encryptChunk(chunk) { const key = await this.$http.get('/api/getEncryptKey'); // 后端返回AES密钥 const iv = crypto.getRandomValues(new Uint8Array(16)); // 随机IV const cipher = new CryptoJS.AES.encrypt( chunk, CryptoJS.enc.Hex.parse(key), { iv: CryptoJS.enc.Hex.parse(iv.toString()) } ); return new Blob([cipher.toString()], { type: 'application/octet-stream' }); } } };
后端:PHP(分片接收+合并+加密存储)

(兼容IE8的表单上传 fallback,用$_FILES接收)

prepare("INSERT INTO upload_progress (hash, chunk_index) VALUES (?, ?) ON DUPLICATE KEY UPDATE chunk_index=?");$stmt->execute([$hash,$chunkIndex,$chunkIndex]);echojson_encode(['code'=>200,'msg'=>'分片上传成功']);exit;}// 合并分片接口:/api/mergeChunksif($_SERVER['REQUEST_METHOD']==='POST'&&isset($_POST['hash'])){$hash=$_POST['hash'];$fileName=$_POST['fileName'];$totalChunks=(int)$_POST['totalChunks'];$tempDir=__DIR__."/uploads/temp/{$hash}";$finalPath=__DIR__."/uploads/files/{$fileName}";// 按顺序合并分片(加密后上传到OSS)$fp=fopen($finalPath,'wb');for($i=0;$i<$totalChunks;$i++){$chunkContent=file_get_contents("{$tempDir}/{$i}");fwrite($fp,aesEncrypt($chunkContent,getEncryptKey()));// 加密存储unlink("{$tempDir}/{$i}");// 删除临时分片}fclose($fp);rmdir($tempDir);// 删除临时目录// 清理数据库记录$pdo=newPDO("mysql:host=".DB_HOST.";dbname=".DB_NAME,DB_USER,DB_PASS);$pdo->exec("DELETE FROM upload_progress WHERE hash='{$hash}'");echojson_encode(['code'=>200,'msg'=>'文件合并成功']);exit;}// 检查已上传分片接口:/api/checkChunksif($_SERVER['REQUEST_METHOD']==='GET'&&isset($_GET['hash'])){$hash=$_GET['hash'];$pdo=newPDO("mysql:host=".DB_HOST.";dbname=".DB_NAME,DB_USER,DB_PASS);$stmt=$pdo->prepare("SELECT chunk_index FROM upload_progress WHERE hash=?");$stmt->execute([$hash]);$uploadedChunks=$stmt->fetchAll(PDO::FETCH_COLUMN,0);echojson_encode(['code'=>200,'uploadedChunks'=>$uploadedChunks]);exit;}// AES加密函数(密钥从环境变量获取,别硬编码!)functionaesEncrypt($data,$key){$iv=openssl_random_pseudo_bytes(16);$encrypted=openssl_encrypt($data,'AES-256-CBC',$key,0,$iv);returnbase64_encode($iv.$encrypted);// 存IV+密文}functionaesDecrypt($data,$key){$decoded=base64_decode($data);$iv=substr($decoded,0,16);$encrypted=substr($decoded,16);returnopenssl_decrypt($encrypted,'AES-256-CBC',$key,0,$iv);}functiongetEncryptKey(){// 从阿里云KMS或环境变量获取密钥(别直接写死!)returngetenv('AES_ENCRYPT_KEY');}?>
兼容IE8的“土味方案”

IE8不支持File APIFormData,只能用传统的iframe模拟异步上传:

// IE8检测 if (/*@cc_on!@*/false) { document.getElementById('fileInput').style.display = 'none'; document.getElementById('ie8FileInput').addEventListener('change', function(e) { document.getElementById('ie8UploadForm').submit(); }); }

吐槽+安利:群里见!

咱最近建了个QQ群(374992201),专门拉拢“被毕业设计逼疯”的兄弟姐妹们~群里福利拉满:

  • 新人加群送1~99元红包(手慢无!);
  • 推荐客户成交拿20%提成(2万项目提4千,比外卖自由香多了!);
  • 大神在线指导代码(不会写?直接@我,远程帮你调!);
  • 内推工作(学长学姐在互联网大厂蹲坑,直接甩岗位链接!)。

咱这毕业设计要是成了,答辩老师看了都得夸“这学生有点东西”~ 赶紧加群,一起卷死同学,顺便搞钱!(PS:群里还有人分享“如何用AI写论文”的玄学技巧,亲测能过查重!)

最后,求师哥师姐推荐工作!福州信息安全行业的岗位,求内推!(鞠躬)

安装环境

PHP:7.2.14

调整块大小

NOSQL

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

SQL

创建数据库

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

配置数据库连接

安装依赖

访问页面进行测试

数据表中的数据

效果预览

文件上传

文件刷新续传

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

文件夹上传

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

免费下载示例

点击下载完整示例

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

FLUX.1-dev-fp8-dit文生图镜像教程:如何自定义添加新SDXL Prompt风格预设

FLUX.1-dev-fp8-dit文生图镜像教程&#xff1a;如何自定义添加新SDXL Prompt风格预设 1. 为什么需要自定义SDXL Prompt风格预设 你可能已经用过FLUX.1-dev-fp8-dit模型生成图片&#xff0c;也试过它内置的几种SDXL Prompt风格——比如“电影感”“胶片风”“赛博朋克”这些一…

作者头像 李华
网站建设 2026/4/16 10:56:56

3.2 高可用架构设计原来可以这样做?

3.2 太震撼!高可用架构设计原来可以这样做? 在构建现代分布式系统时,高可用性是一个至关重要的设计目标。高可用架构能够确保系统在面对各种故障和异常情况时依然能够正常运行,为用户提供持续稳定的服务。本节将深入探讨高可用架构的设计原则和实现方法,并通过实际的Go代…

作者头像 李华
网站建设 2026/4/16 10:56:01

3.2 容错与容灾设计:当第三方服务崩溃时如何保证业务不中断?

3.2 容错与容灾设计:当第三方服务崩溃时如何保证业务不中断? 引言 在构建复杂的分布式系统时,我们不可避免地要依赖各种第三方服务,如短信网关、邮件服务器、微信API等。这些外部依赖往往是系统中最不可控的因素,它们可能因为网络问题、服务过载、维护升级等各种原因而出…

作者头像 李华
网站建设 2026/4/12 19:24:38

dsp28335电机控制板zi料(软件代码) 1.永磁同步电机有传感器三闭环foc控制代码 2

dsp28335电机控制板zi料(软件代码) 1.永磁同步电机有传感器三闭环foc控制代码 2.永磁同步电机无传感器双闭环foc控制代码 3.无刷直流电机有传感器方波控制代码 4.异步电机V/F变频调速控制代码 控制板和驱动版硬件电子资料软件程序CCS6.0环境下运行 DSP28335这玩意儿在电机控制…

作者头像 李华
网站建设 2026/4/11 17:31:26

Qwen3-4B-Instruct效果对比:CPU vs 低配GPU(GTX1650)生成质量实测

Qwen3-4B-Instruct效果对比&#xff1a;CPU vs 低配GPU&#xff08;GTX1650&#xff09;生成质量实测 1. 为什么这款4B模型值得你花时间测试&#xff1f; 你有没有试过这样的场景&#xff1a;想快速写一段带逻辑的Python代码&#xff0c;或者需要润色一封专业邮件&#xff0c…

作者头像 李华
网站建设 2026/4/16 10:54:54

ChatGLM3-6B-128K科研助手:文献综述自动生成系统

ChatGLM3-6B-128K科研助手&#xff1a;文献综述自动生成系统效果实测 1. 科研人的新日常&#xff1a;从堆满PDF到一键生成综述 上周五下午三点&#xff0c;我正对着电脑屏幕上打开的27个PDF文献标签页发呆。这些是导师要求我三天内读完并整理出研究现状的论文&#xff0c;涉及…

作者头像 李华