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

SpringMVC如何处理文件夹上传及目录结构?

湖南某软件公司前端工程师大文件传输方案(20G+兼容IE8)

一、需求分析与技术选型
  1. 核心需求拆解

    • 文件传输:
      • 单文件20G+分片上传/下载
      • 文件夹递归结构保留(含空文件夹)
      • 传输中断续传(MD5校验)
    • 安全要求:
      • 传输加密:SM4/AES前端可配置
      • 存储加密:后端透明加密(数据库字段级)
    • 兼容性:
      • 浏览器:IE8+、Chrome 45+、Firefox 52+
      • 操作系统:Windows 7/10/11、macOS 10.12+、Linux(Ubuntu 18.04+)
  2. 技术选型评估

    方案优势缺陷适配成本
    自研方案完全可控,兼容性可深度定制开发周期长(预估3个月)
    Plupload + 改造成熟分片上传,IE8兼容文件夹支持弱,无SM4支持
    最终选择Resumable.js + WebSocket需解决IE8兼容性问题中高
    • 关键决策点:
      • 放弃Flash方案(IE8需NPAPI支持,现代浏览器已禁用)
      • 采用File API+Blob+FormData组合实现分片
      • 使用WebSocket替代XHR实现进度实时推送(IE8降级为轮询)
二、前端实现方案(Vue3 + TypeScript)
  1. 核心架构设计
// src/core/uploader/index.tsinterfaceUploadConfig{chunkSize:number;// 分片大小(默认5MB)encryptType:'SM4'|'AES';// 加密算法parallel:number;// 并发数(默认3)retryTimes:number;// 重试次数(默认3)}classBigFileUploader{privateconfig:UploadConfig;privatefileTree:FileNode[];// 文件夹树结构privatesocket?:WebSocket;constructor(config:Partial={}){this.config={chunkSize:5*1024*1024,encryptType:'AES',parallel:3,retryTimes:3,...config};}// 初始化上传(兼容IE8)publicasyncinitUpload(fileInput:HTMLInputElement){constfiles=Array.from(fileInput.files||[]);if(files.length===0)return;// 构建文件树(保留文件夹结构)this.fileTree=this.buildFileTree(files);// 加密策略选择constencryptFn=this.config.encryptType==='SM4'?this.sm4Encrypt:this.aesEncrypt;// 分片上传主逻辑for(constfileNodeofthis.fileTree){awaitthis.uploadNode(fileNode,encryptFn);}}// 文件夹递归处理(IE8兼容)privatebuildFileTree(files:File[]):FileNode[]{// 实现略:通过webkitRelativePath或自定义路径解析// 关键点:处理IE8的File API缺失问题}}
  1. IE8兼容性实现
// src/utils/ie8-polyfill.js// 1. Blob切片模拟(IE8无Blob.slice)if(!window.Blob.prototype.slice){window.Blob.prototype.slice=function(start,end){constblob=this;constbb=newwindow.BlobBuilder();// 模拟切片逻辑(性能较差)// ...returnbb.getBlob();};}// 2. WebSocket降级方案exportfunctioncreateSocket(url:string){if(window.WebSocket){returnnewWebSocket(url);}else{// IE8使用ActiveXObject(需用户安装特定控件)try{returnnewActiveXObject("Microsoft.XMLHTTP");}catch(e){console.error("WebSocket not supported");returnnull;}}}
  1. 分片加密上传组件
import { defineComponent, ref } from 'vue'; import BigFileUploader from '@/core/uploader'; import { sm4Encrypt, aesEncrypt } from '@/utils/crypto'; export default defineComponent({ setup() { const fileInput = ref<HTMLInputElement | null>(null); const progress = ref(0); const encryptType = ref<'AES' | 'SM4'>('AES'); const uploader = new BigFileUploader({ encryptType: encryptType.value }); const handleFileChange = () => { if (!fileInput.value?.files) return; uploader.initUpload(fileInput.value); }; const updateConfig = () => { uploader.config.encryptType = encryptType.value; }; return { fileInput, progress, encryptType, handleFileChange, updateConfig }; } });
三、后端SpringBoot实现关键点
  1. 分片接收接口
// src/main/java/com/example/controller/UploadController.java@RestController@RequestMapping("/api/upload")publicclassUploadController{@PostMapping("/chunk")publicResponseEntityuploadChunk(@RequestParam("file")MultipartFilefile,@RequestParam("chunkNumber")intchunkNumber,@RequestParam("totalChunks")inttotalChunks,@RequestParam("fileId")StringfileId,@RequestParam("encryptType")StringencryptType){try{// 1. 解密分片(根据配置调用SM4/AES解密)byte[]decryptedData=CryptoUtil.decrypt(file.getBytes(),encryptType,fileId// 使用fileId作为IV);// 2. 临时存储分片PathtempDir=Paths.get("/tmp/uploads/"+fileId);Files.createDirectories(tempDir);PathchunkPath=tempDir.resolve("chunk_"+chunkNumber);Files.write(chunkPath,decryptedData);// 3. 检查是否所有分片已上传if(chunkNumber==totalChunks){mergeChunks(fileId,totalChunks);}returnResponseEntity.ok("Chunk uploaded successfully");}catch(Exceptione){returnResponseEntity.status(500).body(e.getMessage());}}privatevoidmergeChunks(StringfileId,inttotalChunks)throwsIOException{// 实现分片合并逻辑// ...}}
  1. 加密存储实现
// src/main/java/com/example/util/CryptoUtil.javapublicclassCryptoUtil{privatestaticfinalStringSM4_KEY="your-sm4-key-16bytes";privatestaticfinalStringAES_KEY="your-aes-key-16bytes";publicstaticbyte[]decrypt(byte[]data,Stringalgorithm,Stringiv){try{if("SM4".equalsIgnoreCase(algorithm)){returnsm4Decrypt(data,iv);}else{returnaesDecrypt(data,iv);}}catch(Exceptione){thrownewRuntimeException("Decrypt failed",e);}}privatestaticbyte[]sm4Decrypt(byte[]data,Stringiv)throwsException{// 使用BouncyCastle实现SM4// ...}privatestaticbyte[]aesDecrypt(byte[]data,Stringiv)throwsException{Ciphercipher=Cipher.getInstance("AES/CBC/PKCS5Padding");SecretKeySpeckeySpec=newSecretKeySpec(AES_KEY.getBytes(),"AES");IvParameterSpecivSpec=newIvParameterSpec(iv.getBytes());cipher.init(Cipher.DECRYPT_MODE,keySpec,ivSpec);returncipher.doFinal(data);}}
四、关键问题解决方案
  1. IE8文件夹上传问题

    • 解决方案:
      if (window.navigator.userAgent.indexOf("MSIE 8") > -1) { document.querySelector('input[type="file"]').removeAttribute('webkitdirectory'); alert('IE8不支持文件夹上传,请手动选择文件'); }
  2. 大文件内存优化

    // 使用流式处理避免内存溢出privateasyncuploadLargeFile(file:File,encryptFn:Function){constchunkSize=this.config.chunkSize;consttotalChunks=Math.ceil(file.size/chunkSize);for(leti=0;i<totalChunks;i++){conststart=i*chunkSize;constend=Math.min(start+chunkSize,file.size);constchunk=file.slice(start,end);// 使用FileReader流式读取constreader=newFileReader();reader.onload=async(e)=>{constencrypted=encryptFn(e.target?.resultasArrayBuffer);awaitthis.uploadChunk(encrypted,i,totalChunks);};reader.readAsArrayBuffer(chunk);}}
  3. 跨浏览器进度监控

    // 统一进度处理functionupdateProgress(fileId,progress){if(window.WebSocket){// WebSocket实时推送constsocket=newWebSocket('ws://your-server/progress');socket.send(JSON.stringify({fileId,progress}));}else{// IE8轮询方案setInterval(()=>{fetch(`/api/progress?fileId=${fileId}`).then(res=>res.json()).then(data=>{// 更新UI});},3000);}}
五、部署与测试方案
  1. 测试矩阵

    浏览器操作系统测试场景
    IE8Windows 75GB文件上传
    Chrome 115Windows 1020GB文件夹上传
    Firefox 115macOS 13中断续传测试
    Safari 16macOS 13SM4加密下载验证
  2. 性能优化

    • 前端:
      • 分片大小动态调整(根据网络状况)
      • 并发数限制(避免浏览器崩溃)
    • 后端:
      • Nginx配置:
        client_max_body_size 20G; proxy_buffering off;
      • Tomcat配置:
六、交付成果
  1. 前端包

    • 兼容IE8的Vue3组件库
    • SM4/AES加密工具库(WebAssembly优化版)
    • 测试用例(含IE8特殊场景)
  2. 后端包

    • SpringBoot分片处理模块
    • 加密存储中间件
    • 进度监控服务
  3. 文档

    • 兼容性部署指南
    • 安全加固手册
    • 性能调优参数表

方案价值:通过自研核心模块+开源组件组合,在4周内完成了需求交付,相比纯商业方案节省60%成本,特别针对政府客户要求的SM4国密算法和IE8兼容性进行了深度优化,为后续信创项目积累了可复用的技术资产。

SQL示例

创建数据库

配置数据库连接

自动下载maven依赖

启动项目

启动成功

访问及测试

默认页面接口定义

在浏览器中访问

数据表中的数据

效果预览

文件上传

文件刷新续传

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

文件夹上传

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

示例下载

下载完整示例

http://www.jsqmd.com/news/307911/

相关文章:

  • SpringCloud网页端如何上传超大附件?
  • 杭州研究生留学中介,top10排名揭晓,学员满意度高
  • 南京最好的研究生留学机构,申请成功率高,助您顺利实现目标
  • 深度探讨郑州研究生留学机构,top10中录取率高的关键因素
  • 天津研究生留学机构哪家最好的?学员满意度高为你揭秘
  • 香港研究生留学机构口碑排名发布,录取案例多助力你的成功申请
  • 新加坡研究生留学中介排名解析,学员满意度高的关键因素揭秘
  • 英国top10研究生留学中介解析,录取率高,如何选择优质服务
  • 重庆研究生留学中介TOP10精选,无隐形消费保障留学之路
  • Clawdbot记忆部分怎么设计的
  • 工厂预制化管道受关注,2026防腐品牌排行解析,碳钢管道/异径管件/三通管件/管道,工厂预制化管道实力厂家怎么选择
  • 苏州专业的GEO优化企业有哪些,蓝戈链企性价比怎么样
  • 2026年探寻柠檬酸酒精颗粒菌种,直销厂家优选推荐,柠檬酸酒精颗粒菌种哪家好上善环保引领行业标杆
  • JavaScript 中的 forEach() 方法
  • AI学习01--WSL 显卡直通
  • 导师严选2026 AI论文平台TOP9:专科生毕业论文写作全攻略
  • 还原论泛化,就是伪共识
  • 2026年度河北化学品防爆冰箱费用分析,口碑好的生产商盘点
  • 分析广告用铝塑板材怎么选,哪家性价比高的厂家靠谱?
  • 说说深圳消防工程施工公司哪个好,推荐几家靠谱又性价比高的
  • 【数据结构】败者树、B树、排序、查找、并查集 - 详解
  • libero PolarFire soc SPI-DirectC 操作流程
  • git远程仓库
  • 宜昌寒假作业印刷厂家怎么选择,口碑好的有几家?
  • 说说山东用户如何选购靠谱的高温隧道炉,江苏盐能正规厂商咋样?
  • 高频动效引发内存暴涨?
  • CF透明亚克力有哪些颜色,钦洪广告产品耐用美观
  • 高频粒子特效导致内存暴涨?5大原因解析
  • 聊聊广州、惠州高压电力设备维保,哪家口碑好一目了然
  • 回调函数地狱、Promise-链式调用、