news 2026/6/6 8:44:43

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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依赖

启动项目

启动成功

访问及测试

默认页面接口定义

在浏览器中访问

数据表中的数据

效果预览

文件上传

文件刷新续传

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

文件夹上传

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

示例下载

下载完整示例

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

终端渲染天花板:技术诗《永恒工具》

基于本质铸代码&#xff0c;囹圄效用展智慧。 笔记模板由python脚本于2026-01-27 12:38:48创建&#xff0c;本篇笔记适合终端渲染学习的coder翻阅。 学习的细节是欢悦的历程 博客的核心价值&#xff1a;在于输出思考与经验&#xff0c;而不仅仅是知识的简单复述。 Python官网&a…

作者头像 李华
网站建设 2026/5/29 0:53:28

springboot的高校安全治安管理系统-vue

目录 系统概述技术架构核心功能模块创新点应用价值 开发技术源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01; 系统概述 基于SpringBoot和Vue的高校安全治安管理系统是一个现代化、模块化的平台&#xff0c;旨在提升校园安全管理效率。系…

作者头像 李华
网站建设 2026/6/6 5:13:44

高频动效引发内存暴涨?

你可能遇到过这种场景: 测试同事说:“我就一直点按钮,点了五分钟,游戏内存从 800M 涨到 1.4G,然后啪一下闪退了。” 你一看代码: 没有疯狂 new 没有静态 List 疯狂堆对象 各种事件也都解绑了 GC 跑起来也正常 更离谱的是:只要人不操作,内存就相当稳定,一猛点就嗖嗖涨。…

作者头像 李华
网站建设 2026/5/28 20:10:27

mfc80d.dll文件丢失找不到 免费下载方法

在使用电脑系统时经常会出现丢失找不到某些文件的情况&#xff0c;由于很多常用软件都是采用 Microsoft Visual Studio 编写的&#xff0c;所以这类软件的运行需要依赖微软Visual C运行库&#xff0c;比如像 QQ、迅雷、Adobe 软件等等&#xff0c;如果没有安装VC运行库或者安装…

作者头像 李华
网站建设 2026/6/6 0:23:59

亲测好用!继续教育10款AI论文工具测评与推荐

亲测好用&#xff01;继续教育10款AI论文工具测评与推荐 2026年学术写作工具测评&#xff1a;为何值得一看&#xff1f; 在当前快节奏的学术环境中&#xff0c;论文写作已成为科研工作者必须面对的核心挑战。无论是选题构思、文献检索&#xff0c;还是内容撰写与格式规范&…

作者头像 李华