当前位置: 首页 > news >正文

html5大文件分片上传插件vue-cli项目集成与加密传输

前端老兵的20G文件夹上传血泪史(附部分代码)

各位前端同仁们好,我是老王,一个在福建靠写代码混口饭吃的"前端民工"。最近接了个奇葩项目,客户要求用原生JS实现20G文件夹上传下载,还要兼容IE9!这简直是要了我这把老骨头的命啊!

项目奇葩需求大赏

  1. 20G文件传输:客户说他们每天要传"大量资料",我第一反应是"您这是要传整个互联网吗?"
  2. 文件夹层级保留:要求上传1000个分类的文件,还要保持结构,这比整理我家衣柜还难
  3. 加密传输存储:SM4+AES双加密,我怀疑客户在搞什么国家机密
  4. 断点续传:关闭浏览器、重启电脑都不能丢进度,这比记住女朋友生日还难
  5. 非打包下载:几万个文件单独下载,这是要测试我家网速吗?
  6. 100元预算:是的,你没看错,100块!连我喝咖啡的钱都不够
  7. 免费3年维护:客户说"年轻人要讲武德",我差点把键盘吃了

文件夹上传技术实现(部分代码)

经过我日夜奋战(其实是熬夜掉头发),终于搞定了文件夹上传的核心功能。以下是部分原生JS实现代码:

20G文件夹上传神器(IE9兼容版) .upload-container { padding: 20px; font-family: 'Microsoft YaHei', sans-serif; } .progress-container { margin-top: 20px; border: 1px solid #ddd; padding: 10px; } .file-tree { margin-top: 20px; border: 1px solid #eee; padding: 10px; max-height: 300px; overflow-y: auto; } 文件夹上传系统(IE9兼容版) 选择文件夹 上传进度: 0% 文件夹结构: // 全局变量存储文件信息(IE9兼容的存储方案) const fileStorage = { files: [], currentChunk: 0, totalChunks: 0, uploadId: null, // 模拟本地存储(IE9没有localStorage的完整实现) save: function(key, value) { try { if (window.localStorage) { localStorage.setItem(key, JSON.stringify(value)); } else { // IE9兼容方案 - 使用userData或cookie(这里简化处理) document.cookie = key + '=' + encodeURIComponent(JSON.stringify(value)) + '; path=/'; } } catch (e) { console.error('存储失败:', e); } }, load: function(key) { try { if (window.localStorage) { const value = localStorage.getItem(key); return value ? JSON.parse(value) : null; } else { // IE9兼容方案 const name = key + '='; const ca = document.cookie.split(';'); for(let i=0; i<ca.length; i++) { let c = ca[i]; while (c.charAt(0)==' ') c = c.substring(1); if (c.indexOf(name) == 0) return JSON.parse(decodeURIComponent(c.substring(name.length, c.length))); } return null; } } catch (e) { console.error('读取失败:', e); return null; } } }; // 处理文件夹选择 document.getElementById('folderInput').addEventListener('change', function(e) { const files = e.target.files; if (!files || files.length === 0) return; // 构建文件树结构 const fileTree = buildFileTree(files); document.getElementById('fileTree').innerHTML = renderFileTree(fileTree, ''); // 存储文件信息用于后续上传 fileStorage.files = Array.from(files).map(file => ({ name: file.webkitRelativePath || file.name, size: file.size, type: file.type, lastModified: file.lastModified, chunks: Math.ceil(file.size / (1024 * 1024)) // 每块1MB })); // 初始化上传状态 fileStorage.totalChunks = fileStorage.files.reduce((sum, file) => sum + file.chunks, 0); fileStorage.currentChunk = 0; fileStorage.uploadId = Date.now() + '-' + Math.random().toString(36).substr(2); // 保存上传状态 fileStorage.save('uploadState_' + fileStorage.uploadId, { files: fileStorage.files, currentChunk: 0, totalChunks: fileStorage.totalChunks }); }); // 构建文件树(简化版) function buildFileTree(files) { const tree = {}; Array.from(files).forEach(file => { const pathParts = (file.webkitRelativePath || file.name).split('/'); let currentLevel = tree; pathParts.forEach((part, index) => { if (index === pathParts.length - 1) { // 文件节点 currentLevel[part] = { isFile: true, size: file.size, type: file.type }; } else { // 目录节点 if (!currentLevel[part]) { currentLevel[part] = {}; } currentLevel = currentLevel[part]; } } }); }); return tree; } // 渲染文件树(简化版) function renderFileTree(tree, path) { let html = '<ul>'; for (const key in tree) { const node = tree[key]; const currentPath = path ? path + '/' + key : key; if (node.isFile) { html += `<li>${key} (${formatFileSize(node.size)})</li>`; } else { html += `<li><strong>${key}/</strong>`; html += renderFileTree(node, currentPath); html += '</li>'; } } html += '</ul>'; return html; } // 格式化文件大小 function formatFileSize(bytes) { if (bytes === 0) return '0 Bytes'; const k = 1024; const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; } // 模拟上传过程(实际项目中需要替换为真实的AJAX请求) function startUpload() { if (fileStorage.files.length === 0) return; // 这里应该实现分块上传逻辑 // 由于篇幅限制,只展示进度更新部分 const interval = setInterval(() => { fileStorage.currentChunk++; const progress = Math.min(100, Math.round((fileStorage.currentChunk / fileStorage.totalChunks) * 100)); document.getElementById('progressText').textContent = progress + '%'; document.getElementById('uploadProgress').value = progress; // 保存进度 fileStorage.save('uploadProgress_' + fileStorage.uploadId, { progress: progress, currentChunk: fileStorage.currentChunk, totalChunks: fileStorage.totalChunks }); if (progress >= 100) { clearInterval(interval); alert('上传完成!(模拟)'); } }, 500); // 模拟上传速度 } // 页面加载时检查是否有未完成的上传 window.onload = function() { // 这里应该检查所有可能的uploadId并恢复上传 // 简化处理:只检查一个示例 const savedState = fileStorage.load('uploadProgress_example123'); if (savedState && savedState.progress > 0 && savedState.progress < 100) { if (confirm('检测到未完成的上传,是否继续?')) { document.getElementById('progressText').textContent = savedState.progress + '%'; document.getElementById('uploadProgress').value = savedState.progress; // 实际项目中需要恢复上传状态 } } };

开发过程中的血泪教训

  1. IE9兼容性

    • 文件夹上传需要使用webkitdirectory属性,但IE不支持
    • 最终解决方案:告诉客户"升级浏览器或使用Chrome框架"
  2. 大文件处理

    • 20G文件不能一次性读取到内存,必须分块
    • 使用了File API的slice方法实现分块
  3. 断点续传

    • 使用localStorage/cookie存储上传进度(IE9兼容方案)
    • 实际项目中应该使用IndexedDB或后端存储
  4. 加密传输

    • 使用了crypto-js库实现AES加密(但客户预算100元买不起库)
    • 最终解决方案:让后端同学实现加密
  5. 文件夹结构保留

    • 使用webkitRelativePath获取文件相对路径
    • 构建树形结构存储文件夹层级

真诚建议

各位同行,遇到这种项目请慎重考虑:

  1. 100元预算连买杯星巴克都不够
  2. 免费维护3年?不如直接让我给你打工
  3. 20G文件传输在浏览器端实现?这是要发明新的互联网协议吗?

加入我们的接单群

虽然这个项目让我掉了一把头发,但我还是决定继续在前端这条路上走下去。欢迎加入我们的接单群:374992201

群内福利:

  • 加群送1-99元红包
  • 推荐项目拿20%提成
  • 超级会员享50%提成
  • 不定期分享技术资源和接单技巧

最后说一句:前端不易,且行且珍惜。如果这个项目能做下来,我考虑转行去卖生发液了…

将组件复制到项目中

示例中已经包含此目录

引入组件

配置接口地址

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

处理事件

启动测试

启动成功

效果

数据库

效果预览

文件上传

文件刷新续传

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

文件夹上传

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

下载示例

点击下载完整示例

http://www.zskr.cn/news/157502.html

相关文章:

  • vue大文件分片上传插件源码解读及加密传输解决方案
  • 揭秘智谱Open-AutoGLM开源项目:5大核心功能你必须掌握
  • FastReport报表怎么控制行数?动态扩展与固定行数技巧
  • 5个核心概念助你理解YashanDB数据库的架构
  • PaddlePaddle框架的LayerDrop技术对模型稳定性的影响
  • 为什么顶尖机构都在研究Open-AutoGLM?,深入剖析其命名逻辑与技术野心
  • 为什么顶尖团队开始从CodeWhisperer转向Open-AutoGLM?真相曝光
  • 工会福利推荐公司排名揭秘,中远奇牧性价比之选 - 工业设备
  • 百度自研PaddlePaddle框架为何能支撑千亿参数模型?
  • 【Open-AutoGLM插件深度揭秘】:Chrome浏览器中的AI自动化神技,你真的会用吗?
  • PaddlePaddle框架的Warmup学习率预热策略设置
  • 背调平台如何成为HR招聘中的关键“拼图”?
  • 别墅泳池边岩板怎么选?抗菌功能与选择标准全解析 - 工业推荐榜
  • Qwen-Edit-2509:AI图像编辑与多角度生成的终极解决方案
  • 智普AutoGLM开源首秀:6大亮点功能全面解读,错过再等一年
  • 2025年天津低升糖食品品牌排行榜,一萱久降堂低升糖指数食品的市场评价如何 - 工业品网
  • 2025年四川省舞台机械厂家推荐:桁架/灯光架/舞台/网架/合唱台全流程实力厂商一览 - 深度智识库
  • PaddlePaddle框架的多头注意力(Multi-Head Attention)底层实现
  • 数字化转型的第一步:不是上系统,而是拆掉“数据孤岛”
  • 2025年北京定制化企业文化咨询排行榜,专业机构推荐及本地服务商测评 - 工业设备
  • 这5家C++培训机构服务超棒,选它学编程不踩坑! - 速递信息
  • 2025年液压中心架认证厂家排行榜,新测评精选液压中心架知名厂家推荐 - 工业品牌热点
  • AutoGLM来了,大模型自动微调时代还远吗?
  • 基本的路由选择协议
  • 2025年三相固态继电器制造企业权威推荐榜单:单相固态继电器/直流固态继电器 /多路固态继电器源头厂家精选 - 品牌推荐官
  • 2025专业声音克隆免费软件测评,这款工具给12万字符 - 速递信息
  • 15款必玩单人/网上休闲游戏小程序推荐!手机打发时间的微信小游戏 - 速递信息
  • 【性能提升300%】Ollama部署Open-AutoGLM优化秘籍首次公开
  • 哪个工具降AI率效果最好?2025年降AICG工具专业评估指南!亲测这10个平台,学生党必看!这个真能把AI率降下去! - 晨晨_分享AI
  • 如何快速使用Steamless:DRM移除完整指南