news 2026/3/13 9:29:56

工程建筑网页如何通过js实现大文件分片上传及秒传源码?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
工程建筑网页如何通过js实现大文件分片上传及秒传源码?

前端老炮的20G文件夹上传大冒险(附部分代码)

各位前端同仁们,我是老张,一个在辽宁苦哈哈写代码的"前端民工"。最近接了个活,客户要求用原生JS实现20G文件夹上传下载,还要支持IE9!这简直是要了我这把老骨头的命啊!不过为了那100块预算(划掉),为了技术理想,我决定拼了!

项目背景(哭诉版)

客户要求:

  • 20G大文件上传(这是要上传整个硬盘吗?)
  • 文件夹上传保留层级结构(1000个分类的文件,这是要搞文件管理系统吗?)
  • 支持SM4/AES加密(这是要搞国家机密吗?)
  • 断点续传(用户重启电脑都不能丢进度,这是要我做操作系统吗?)
  • 兼容IE9(现在还有人用IE9?哦,是Windows 7用户,好吧,我理解)
  • 预算100元以内(这连买杯咖啡都不够啊!)
  • 7*24小时技术支持(这是要把我当24小时客服吗?)
  • 3年免费维护(这是要签终身合同吗?)

技术选型(妥协版)

经过深思熟虑,我决定:

  • 前端:Vue3 + 原生JS(因为客户说不能用WebUploader)
  • 后端:SpringBoot(但我不写后端代码,哈哈)
  • 加密:crypto-js(因为IE9不支持Web Crypto API)
  • 文件分片:自己实现(因为找不到现成的IE9兼容方案)

部分前端代码(救命版)

以下是文件夹上传的核心代码,其他功能你们自己实现吧(逃):

20G文件夹上传神器(IE9兼容版) body { font-family: 'Microsoft YaHei', sans-serif; margin: 20px; } .progress-container { width: 100%; background: #f0f0f0; margin: 10px 0; } .progress-bar { height: 20px; background: #4CAF50; width: 0%; text-align: center; line-height: 20px; color: white; } .file-list { margin-top: 20px; border: 1px solid #ddd; padding: 10px; max-height: 300px; overflow-y: auto; } 20G文件夹上传神器(IE9兼容版) 选择文件夹 开始上传 暂停上传 0% 文件列表: // 全局变量(IE9兼容的"类"实现) var FileUploader = { files: [], chunkSize: 5 * 1024 * 1024, // 5MB分片 uploadId: null, paused: false, // 初始化(IE9兼容版) init: function() { document.getElementById('fileInput').addEventListener('change', this.handleFileSelect.bind(this)); // 模拟断点续传的本地存储(IE9用userData或cookie,这里简化用localStorage) if (!localStorage.getItem('uploadProgress')) { localStorage.setItem('uploadProgress', JSON.stringify({})); } }, // 处理文件夹选择(IE9兼容版) handleFileSelect: function(e) { this.files = []; var fileList = e.target.files; // 递归构建文件树(IE9没有File.webkitRelativePath,需要特殊处理) for (var i = 0; i < fileList.length; i++) { var file = fileList[i]; // 这里简化处理,实际需要解析webkitRelativePath或手动构建路径 // 兼容IE9的替代方案:让用户先压缩成zip...(开玩笑的) this.files.push({ file: file, path: file.name, // 实际应该用webkitRelativePath uploaded: 0, total: file.size, chunks: Math.ceil(file.size / this.chunkSize), uploadedChunks: 0 }); } this.renderFileList(); }, // 渲染文件列表(IE9兼容版) renderFileList: function() { var list = document.getElementById('fileList'); list.innerHTML = ''; for (var i = 0; i < this.files.length; i++) { var file = this.files[i]; var item = document.createElement('li'); item.innerHTML = file.path + ' (' + this.formatFileSize(file.uploaded) + '/' + this.formatFileSize(file.total) + ')'; list.appendChild(item); } }, // 格式化文件大小(IE9兼容版) formatFileSize: function(bytes) { if (bytes === 0) return '0 Bytes'; var k = 1024; var sizes = ['Bytes', 'KB', 'MB', 'GB']; var i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; }, // 开始上传(IE9兼容版) startUpload: function() { if (this.files.length === 0) { alert('请先选择文件夹'); return; } this.paused = false; this.uploadId = new Date().getTime(); // 简单生成上传ID // 加载之前的上传进度 var progressData = JSON.parse(localStorage.getItem('uploadProgress')); for (var i = 0; i < this.files.length; i++) { var file = this.files[i]; var fileId = file.path; // 实际应该用更唯一的ID // 如果有之前的上传记录,从断点继续 if (progressData[fileId] && progressData[fileId].uploadId === this.uploadId) { file.uploaded = progressData[fileId].uploaded; file.uploadedChunks = progressData[fileId].uploadedChunks; } else { progressData[fileId] = { uploadId: this.uploadId, uploaded: 0, uploadedChunks: 0 }; } } localStorage.setItem('uploadProgress', JSON.stringify(progressData)); this.uploadNextChunk(); }, // 上传下一个分片(IE9兼容版) uploadNextChunk: function() { if (this.paused) return; var fileToUpload = null; var fileIndex = -1; // 查找下一个需要上传的分片 for (var i = 0; i < this.files.length; i++) { var file = this.files[i]; if (file.uploadedChunks < file.chunks) { fileToUpload = file; fileIndex = i; break; } } if (!fileToUpload) { alert('上传完成!'); return; } var chunkIndex = fileToUpload.uploadedChunks; var start = chunkIndex * this.chunkSize; var end = Math.min(start + this.chunkSize, fileToUpload.total); var chunk = fileToUpload.file.slice(start, end); // 加密分片(IE9兼容版) var encryptedChunk = this.encryptData(chunk, 'secret-key-123'); // 实际应该用用户提供的密钥 // 模拟上传(实际应该用XMLHttpRequest或ActiveXObject for IE9) console.log('上传分片:', fileToUpload.path, '分片', chunkIndex, '/', fileToUpload.chunks); // 更新进度(IE9兼容版) fileToUpload.uploadedChunks++; fileToUpload.uploaded = end; // 保存上传进度 var progressData = JSON.parse(localStorage.getItem('uploadProgress')); var fileId = fileToUpload.path; progressData[fileId] = { uploadId: this.uploadId, uploaded: fileToUpload.uploaded, uploadedChunks: fileToUpload.uploadedChunks }; localStorage.setItem('uploadProgress', JSON.stringify(progressData)); // 更新UI this.renderFileList(); this.updateProgressBar(); // 继续上传下一个分片(使用setTimeout模拟异步) var self = this; setTimeout(function() { self.uploadNextChunk(); }, 100); // 模拟网络延迟 }, // 加密数据(IE9兼容版) encryptData: function(data, key) { // 实际应该用SM4或AES,这里简化用CryptoJS的AES // IE9需要额外处理ArrayBuffer到WordArray的转换 if (data instanceof Blob) { return new Promise(function(resolve) { var reader = new FileReader(); reader.onload = function(e) { var words = CryptoJS.enc.Latin1.parse(e.target.result); var encrypted = CryptoJS.AES.encrypt(words, key).toString(); resolve(encrypted); }; reader.readAsBinaryString(data); }); } // 简化处理,实际需要更复杂的实现 return CryptoJS.AES.encrypt(data, key).toString(); }, // 暂停上传(IE9兼容版) pauseUpload: function() { this.paused = true; alert('上传已暂停'); }, // 更新进度条(IE9兼容版) updateProgressBar: function() { var totalUploaded = this.files.reduce(function(sum, file) { return sum + file.uploaded; }, 0); var totalSize = this.files.reduce(function(sum, file) { return sum + file.total; }, 0); var percent = Math.round((totalUploaded / totalSize) * 100); document.getElementById('progressBar').style.width = percent + '%'; document.getElementById('progressBar').innerHTML = percent + '%'; } }; // 初始化(页面加载时执行) window.onload = function() { FileUploader.init(); // 兼容IE9的console.log(IE9没有console对象时) if (!window.console) { window.console = { log: function() {} }; } }; // 暴露全局方法(IE9兼容) window.startUpload = function() { FileUploader.startUpload(); }; window.pauseUpload = function() { FileUploader.pauseUpload(); };

开发心得(吐槽版)

  1. IE9兼容性:这简直是一场噩梦!没有File API,没有Promise,没有const/let,没有箭头函数…我感觉自己在用石器时代的工具开发火箭。

  2. 文件夹上传:现代浏览器有webkitRelativePath,但IE9没有。解决方案?要么让用户先压缩成zip,要么…算了,还是压缩吧(客户肯定不同意)。

  3. 断点续传:localStorage在IE9中只有5MB限制,存储大量上传进度?呵呵,祝你好运。

  4. 加密传输:IE9不支持Web Crypto API,只能用crypto-js这种老库,性能感人。

  5. 20G文件:分片上传是必须的,但IE9的内存管理…算了,别让浏览器崩溃就是胜利。

加入我们的接单群(广告版)

各位同仁,如果你也在为这些奇葩需求头疼,或者想找项目合作,欢迎加入我们的QQ群:374992201

群内福利:

  • 1~99元超级大红包(每天都有)
  • 接单合作机会
  • 技术交流分享
  • 推荐项目拿20%提成
  • 超级会员50%提成(躺着赚钱)

免责声明(求生版)

以上代码仅供娱乐参考,实际项目中请:

  1. 使用成熟的库(如WebUploader、Plupload等)
  2. 考虑使用Flash作为IE9的备选方案
  3. 对于20G文件,建议使用专业的大文件传输方案
  4. 加密传输请使用标准协议(如TLS)而非前端加密
  5. 断点续传最好由后端实现

最后,祝大家项目顺利,少遇奇葩需求!如果真有客户找上门,记得推荐给我啊(手动狗头)!

将组件复制到项目中

示例中已经包含此目录

引入组件

配置接口地址

接口地址分别对应:文件初始化,文件数据上传,文件进度,文件上传完毕,文件删除,文件夹初始化,文件夹删除,文件列表
参考:http://www.ncmem.com/doc/view.aspx?id=e1f49f3e1d4742e19135e00bd41fa3de

处理事件

启动测试

启动成功

效果

数据库

效果预览

文件上传

文件刷新续传

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

文件夹上传

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

下载示例

点击下载完整示例

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

基于大数据的淘宝月季销售预测数据可视化系统 爬虫

目录爬虫技术摘要数据处理与分析系统价值开发技术路线相关技术介绍核心代码参考示例结论源码lw获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;爬虫技术摘要 淘宝月季销售预测数据可视化系统的爬虫模块旨在高效获取商品销售、评价及用户行为数据…

作者头像 李华
网站建设 2026/3/10 15:09:57

基于python框架的房产交易服务平台的设计与实现

目录房产交易服务平台的设计与实现摘要开发技术路线相关技术介绍核心代码参考示例结论源码lw获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;房产交易服务平台的设计与实现摘要 该平台基于Python框架开发&#xff0c;旨在为用户提供高效、安全的…

作者头像 李华
网站建设 2026/3/13 7:21:34

LLM提示工程让遗传咨询更精准

&#x1f4dd; 博客主页&#xff1a;Jax的CSDN主页 LLM提示工程&#xff1a;精准遗传咨询的革命性突破 目录 LLM提示工程&#xff1a;精准遗传咨询的革命性突破 引言&#xff1a;遗传咨询的精准化困局 一、提示工程如何重塑遗传咨询全流程 1. 从痛点到价值&#xff1a;维度一的…

作者头像 李华
网站建设 2026/2/23 9:21:40

基于51/STM32单片机自动售货机扫码支付无人超市缺货补货语音设计(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_文章底部可以扫码

基于51/STM32单片机自动售货机扫码支付无人超市缺货补货语音设计STM32-S144-4种商品4路步进电机出货选货支付库存缺货提醒找零声光提醒按键TFT彩屏(无线方式选择) STM32-S144N无无线-无APP版: STM32-S144B蓝牙无线-APP版: STM32-S144W-WIFI无线-APP版: STM32-S144CAN-视频监控W…

作者头像 李华
网站建设 2026/3/13 3:56:59

免费Claude接入终极指南:5分钟搭建个人AI代理服务

免费Claude接入终极指南&#xff1a;5分钟搭建个人AI代理服务 【免费下载链接】AIClient-2-API Simulates Gemini CLI, Qwen Code, and Kiro client requests, compatible with the OpenAI API. It supports thousands of Gemini model requests per day and offers free use o…

作者头像 李华
网站建设 2026/3/4 4:19:06

高效VR视频下载全攻略:N_m3u8DL-RE专业工具深度解析

高效VR视频下载全攻略&#xff1a;N_m3u8DL-RE专业工具深度解析 【免费下载链接】N_m3u8DL-RE 跨平台、现代且功能强大的流媒体下载器&#xff0c;支持MPD/M3U8/ISM格式。支持英语、简体中文和繁体中文。 项目地址: https://gitcode.com/GitHub_Trending/nm3/N_m3u8DL-RE …

作者头像 李华