news 2026/3/21 20:30:24

JSP中如何利用分段技术实现百万文件上传优化?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
JSP中如何利用分段技术实现百万文件上传优化?

📌毕业设计求生指南:大文件上传系统(兼容IE8版)

😩 现状描述

大家好,我是浙江某三本计算机专业的大三学生,马上要毕业了,现在被导师逼着搞一个**「支持10G文件上传的系统」**,要求如下:

  1. 必须用原生JS(不能用jQuery等库)
  2. 支持IE8及国产浏览器(龙芯、红莲花、奇安信)
  3. 支持文件夹上传(保留层级结构)
  4. 断点续传(重启电脑也不能丢进度)
  5. 加密传输+存储(AES/SM4)
  6. 后端用SpringBoot(我Java还没学透)
  7. 前端用Vue3(但导师说IE8不支持,让我用原生JS)
  8. 对象存储用阿里云OSS(但学校服务器是本地CentOS虚拟机)

💢 最气的是:网上找的代码要么只能传5MB小文件,要么文件夹上传是残废的,最离谱的是作者连个联系方式都不留,出了问题只能对着屏幕喊**「爸爸救我」**……


💡 解决方案(抄作业版)

🖥️ 前端部分(原生JS + 兼容IE8)

1. 文件选择与文件夹上传(兼容IE8)

// FileUploader.js(兼容IE8的魔改版)functionFileUploader(containerId,config){this.config=Object.assign({chunkSize:5*1024*1024,// 5MB分片maxRetry:3,encrypt:true},config);// 检测浏览器类型(IE8特殊处理)this.isIE8=!!window.ActiveXObject&&!document.addEventListener;// 初始化UIthis.initUI(containerId);}FileUploader.prototype.initUI=function(containerId){constcontainer=document.getElementById(containerId);container.innerHTML=`开始上传`;// IE8用Flash模拟文件夹选择(伪代码)if(this.isIE8){this.setupIE8Fallback();}// 绑定事件document.getElementById('startBtn').addEventListener('click',()=>{constfiles=document.getElementById('fileInput').files;this.handleFiles(files);});};// 处理文件(支持文件夹层级)FileUploader.prototype.handleFiles=function(files){constfileTree={};// 遍历文件,构建层级结构for(leti=0;i<files.length;i++){constfile=files[i];constpath=this.isIE8?file.name:file.webkitRelativePath;constparts=path.split('/');letcurrent=fileTree;for(letj=0;j<parts.length-1;j++){constdir=parts[j];if(!current[dir]){current[dir]={};}current=current[dir];}current[parts[parts.length-1]]=file;}// 开始上传this.uploadFileTree(fileTree);};

2. 分片上传 + 断点续传(支持离线保存进度)

// 分片上传核心逻辑FileUploader.prototype.uploadFile=function(file,relativePath=''){constfileId=this.generateFileId(file);consttotalChunks=Math.ceil(file.size/this.config.chunkSize);letcurrentChunk=0;// 从本地存储加载进度constsavedProgress=this.loadProgress(fileId);if(savedProgress){currentChunk=savedProgress.currentChunk;}constuploadChunk=()=>{if(currentChunk>=totalChunks){this.onUploadComplete(fileId,relativePath);return;}conststart=currentChunk*this.config.chunkSize;constend=Math.min(start+this.config.chunkSize,file.size);constchunk=file.slice(start,end);// 加密处理(伪代码)letencryptedChunk=chunk;if(this.config.encrypt){encryptedChunk=this.encryptData(chunk);// 实际要用SM4/AES库}constformData=newFormData();formData.append('fileId',fileId);formData.append('chunkIndex',currentChunk);formData.append('totalChunks',totalChunks);formData.append('relativePath',relativePath);formData.append('file',newBlob([encryptedChunk]));// 发送请求(兼容IE8的XMLHttpRequest)constxhr=this.createXHR();xhr.open('POST','/api/upload',true);xhr.onload=()=>{if(xhr.status===200){currentChunk++;// 保存进度到localStoragethis.saveProgress(fileId,{currentChunk,totalChunks,fileName:file.name,relativePath});uploadChunk();}else{// 重试机制if(this.retryCount<this.config.maxRetry){this.retryCount++;setTimeout(uploadChunk,1000);}}};xhr.send(formData);};uploadChunk();};// 兼容IE8的XHR创建FileUploader.prototype.createXHR=function(){try{returnnewXMLHttpRequest();}catch(e){try{returnnewActiveXObject('Msxml2.XMLHTTP');}catch(e){returnnewActiveXObject('Microsoft.XMLHTTP');}}};

3. 断点续传持久化(localStorage + IE8降级方案)

// 保存上传进度FileUploader.prototype.saveProgress=function(fileId,progress){try{if(window.localStorage){localStorage.setItem(`upload_${fileId}`,JSON.stringify(progress));}else{// IE7及以下用userData存储(更古老的方案)this.saveToUserData(fileId,progress);}}catch(e){console.error('保存进度失败:',e);}};// 加载上传进度FileUploader.prototype.loadProgress=function(fileId){try{if(window.localStorage){constdata=localStorage.getItem(`upload_${fileId}`);returndata?JSON.parse(data):null;}// IE7及以下方案...}catch(e){console.error('加载进度失败:',e);returnnull;}};

🛠️ 后端部分(SpringBoot)

1. 文件分片接收控制器

@RestController@RequestMapping("/api/upload")publicclassFileUploadController{@Value("${oss.endpoint}")privateStringossEndpoint;@PostMappingpublicResponseEntityhandleFileUpload(@RequestParam("fileId")StringfileId,@RequestParam("chunkIndex")intchunkIndex,@RequestParam("totalChunks")inttotalChunks,@RequestParam("relativePath")StringrelativePath,@RequestParam("file")MultipartFilefile){try{// 1. 验证分片(防止恶意上传)if(chunkIndex<0||chunkIndex>=totalChunks){returnResponseEntity.badRequest().body("Invalid chunk index");}// 2. 保存到临时目录(实际项目用OSS)PathtempDir=Paths.get(System.getProperty("java.io.tmpdir"),"uploads",fileId);Files.createDirectories(tempDir);PathchunkPath=tempDir.resolve(chunkIndex+".part");Files.write(chunkPath,file.getBytes(),StandardOpenOption.CREATE);// 3. 如果是最后一个分片,合并文件if(chunkIndex==totalChunks-1){mergeFile(fileId,tempDir,totalChunks,relativePath);}returnResponseEntity.ok("Chunk uploaded successfully");}catch(Exceptione){returnResponseEntity.status(500).body("Upload failed: "+e.getMessage());}}privatevoidmergeFile(StringfileId,PathtempDir,inttotalChunks,StringrelativePath)throwsIOException{PathoutputPath=Paths.get(System.getProperty("java.io.tmpdir"),"uploads",fileId+".dat");try(OutputStreamout=Files.newOutputStream(outputPath,StandardOpenOption.CREATE)){for(inti=0;i<totalChunks;i++){PathchunkPath=tempDir.resolve(i+".part");Files.copy(chunkPath,out);Files.delete(chunkPath);// 清理分片}}// TODO: 上传到OSS并加密存储}}

2. 加密存储服务(SM4示例)

@ServicepublicclassCryptoService{// 使用BouncyCastle实现SM4(实际项目需要引入依赖)publicbyte[]encryptSM4(byte[]data,byte[]key)throwsException{SM4Engineengine=newSM4Engine();BufferedBlockCiphercipher=newPaddedBufferedBlockCipher(newCBCBlockCipher(engine));cipher.init(true,newParametersWithIV(newKeyParameter(key),newbyte[16]));byte[]output=newbyte[cipher.getOutputSize(data.length)];intbytesWritten=cipher.processBytes(data,0,data.length,output,0);bytesWritten+=cipher.doFinal(output,bytesWritten);returnArrays.copyOf(output,bytesWritten);}}

🎯 生存指南

  1. IE8兼容性

    • 用Flash作为降级方案(虽然很古老但有效)
    • 避免使用ES6+语法(用Babel转译)
    • 测试用Windows 7 + IE9虚拟机(学校机房同款)
  2. 大文件上传技巧

    • 分片大小控制在5-10MB
    • 使用Web Worker处理加密(避免UI卡顿)
    • 服务器端验证分片完整性
  3. 找工作秘籍

    • 把毕业设计包装成「企业级文件传输系统」
    • 重点强调「兼容信创环境」(国企/银行很吃这套)
    • 在GitHub挂个Demo(记得把测试账号密码写进README)

📢 最后吐槽:求各位大佬加群374992201啊!送红包是假的,但找工作互助是真的!群里还有大佬在阿里云/华为上班,说不定能内推呢~(群文件有完整项目代码和SQL脚本)


🚀 完整代码获取方式

  1. 加QQ群:374992201(送1~99元红包)
  2. GitHub:https://github.com/your-repo/file-uploader(待补充)
  3. 直接联系作者:QQ/微信在群公告

🙏 跪求大佬指导!毕业答辩就靠这个了!

导入项目

导入到Eclipse:点击查看教程
导入到IDEA:点击查看教程
springboot统一配置:点击查看教程

工程

NOSQL

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

创建数据表

选择对应的数据表脚本,这里以SQL为例

修改数据库连接信息

访问页面进行测试

文件存储路径

up6/upload/年/月/日/guid/filename

效果预览

文件上传

文件刷新续传

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

文件夹上传

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

下载示例

点击下载完整示例

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

PyTorch 全面介绍

PyTorch 是由 Facebook&#xff08;现 Meta&#xff09;人工智能研究院开发的开源机器学习框架&#xff0c;主打 “灵活、易用、动态计算图”&#xff0c;是当前深度学习领域最主流的工具之一&#xff0c;不管是科研实验、算法原型开发&#xff0c;还是工业级部署&#xff0c;都…

作者头像 李华
网站建设 2026/3/20 4:03:44

【time-rs】Format 错误枚举详解(error/format.rs)

这段Rust代码定义了一个格式化错误类型&#xff0c;用于处理时间或数据结构格式化过程中的各种错误情况。 主要用途 用于表示在格式化数据结构&#xff08;特别是时间相关结构&#xff09;时可能发生的各种错误。 代码结构分析 1. 枚举定义 #[non_exhaustive] #[derive(Debug)]…

作者头像 李华
网站建设 2026/3/17 1:11:29

【拯救HMI】从静态到动态:利用数据可视化提升HMI洞察力

现代HMI的强大之处在于能将海量数据转化为直观的视觉洞察。本文将介绍如何通过趋势图、仪表盘、KPI看板和动画&#xff0c;让数据“开口说话”。正文&#xff1a;趋势图&#xff1a; 用于分析过程变量的历史变化&#xff0c;是进行故障诊断和工艺优化的利器。支持多变量同图对比…

作者头像 李华
网站建设 2026/3/15 11:30:19

毕业设计项目 基于设深度学习的人脸性别年龄识别系统

文章目录0 前言1 课题描述课题意义2 实现效果3 算法实现原理3.1 数据集3.2 深度学习识别算法3.3 特征提取主干网络3.4 总体实现流程4 具体实现4.1 预训练数据格式4.2 部分实现代码0 前言 今天学长向大家介绍一个基于深度学习机器视觉的项目&#xff0c;人脸性别年龄识别系统&am…

作者头像 李华