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

跨平台大文件上传在SpringBoot中的实现与讨论

超大文件传输系统技术方案(100GB级)

——基于信创环境的SM4国密加密与FastDFS分布式存储集成

一、项目背景与核心需求

作为北京某国企技术负责人,我司承担的政府招投标项目需实现100GB级超大文件安全传输,并深度集成至现有JSP业务系统。核心需求包括:

  1. 超大文件支持:100GB文件及文件夹(保留层级结构)上传/下载
  2. 国密加密存储:全程采用SM4算法加密,支持FastDFS分布式存储
  3. 全浏览器兼容:IE8+及国产浏览器(奇安信/红莲花/龙芯)
  4. 信创生态适配
    • 数据库:达梦DM8/人大金仓V8/MySQL 8/Oracle 19c/SQL Server 2019
    • 存储:FastDFS集群(需支持国密加密)
    • 操作系统:中标麒麟/统信UOS/银河麒麟
  5. 源码级可控:提供完整源代码,支持二次开发(如与CA证书集成)

二、技术选型与架构设计
1. 分层架构设计

用户终端

Web前端

JSP服务端

国密加密服务

FastDFS存储集群

SM4硬件加速卡

存储节点

2. 关键组件选型
组件类型选型方案国产化适配说明
前端框架Vue 2.6 + jQuery 1.12(IE8兼容)通过polyfill实现ES5兼容
分片上传自定义实现(基于Blob API)兼容IE10+的File API回退方案
国密算法GMSSL 2.5(开源)编译WebAssembly模块供前端调用
服务端Spring Boot 2.7 + JSP通过Tomcat 9.0.x支持JSP
分布式存储FastDFS 6.0 + Nginx扩展FastDFS插件支持SM4加密存储
数据库MyBatis-Plus + ShardingSphere支持多数据源动态切换

三、核心代码实现
1. 前端超大文件分片上传(Vue2 + jQuery)
// SM4加密工具类(WebAssembly封装)classSM4Crypto{constructor(){this.module=null;this.initPromise=this._loadWasm();}async_loadWasm(){constresponse=awaitfetch('/static/sm4.wasm');constbuffer=awaitresponse.arrayBuffer();this.module=awaitWebAssembly.instantiate(buffer);returnthis.module;}asyncencryptChunk(chunk,key){awaitthis.initPromise;constencrypted=this.module.exports.sm4_encrypt(newUint8Array(chunk),newUint8Array(key.padEnd(32,'\0')));returnnewUint8Array(encrypted);}}// 文件夹上传处理器(递归遍历文件树)classFolderUploader{constructor(options){this.sm4=newSM4Crypto();this.chunkSize=10*1024*1024;// 10MB分片this.fileId=this._generateFileId();}async_uploadFile(file,relativePath=''){consttotalChunks=Math.ceil(file.size/this.chunkSize);constkey=awaitthis._fetchEncryptionKey();// 从服务端获取密钥for(leti=0;i<totalChunks;i++){constchunk=file.slice(i*this.chunkSize,(i+1)*this.chunkSize);constencrypted=awaitthis.sm4.encryptChunk(awaitchunk.arrayBuffer(),key);constformData=newFormData();formData.append('file',newBlob([encrypted]));formData.append('chunkIndex',i);formData.append('totalChunks',totalChunks);formData.append('fileId',this.fileId);formData.append('relativePath',relativePath);formData.append('fileName',file.name);formData.append('fileSize',file.size);await$.ajax({url:'/api/upload/chunk',type:'POST',data:formData,processData:false,contentType:false});}}asyncuploadFolder(folderEntry){constreader=folderEntry.createReader();constentries=awaitnewPromise(resolve=>reader.readEntries(resolve));for(constentryofentries){if(entry.isFile){awaitthis._uploadFile(awaitnewPromise(resolve=>entry.file(resolve)),entry.fullPath);}elseif(entry.isDirectory){awaitthis.uploadFolder(entry);// 递归处理子目录}}}}
2. 服务端JSP集成(Spring Boot Controller)
@RestController@RequestMapping("/api/upload")publicclassChunkUploadController{@AutowiredprivateFastDFSClientfastDFSClient;@Value("${sm4.key.path}")privateStringkeyPath;@PostMapping("/chunk")publicResponseEntityhandleChunk(@RequestParam("file")MultipartFilefile,@RequestParamLongchunkIndex,@RequestParamLongtotalChunks,@RequestParamStringfileId,@RequestParamStringrelativePath,@RequestParamStringfileName,@RequestParamLongfileSize){try{// 1. 解密分片(实际需调用GMSSL库)byte[]decrypted=decryptChunk(file.getBytes());// 2. 暂存分片到本地(FastDFS需整体上传,故先合并)PathtempDir=Paths.get("/tmp/chunks",fileId);Files.createDirectories(tempDir);Files.write(tempDir.resolve("chunk_"+chunkIndex),decrypted);// 3. 如果是最后一片,合并并上传FastDFSif(chunkIndex==totalChunks-1){PathmergedFile=mergeChunks(tempDir,fileId,fileSize);StringfastDFSPath=uploadToFastDFS(mergedFile,relativePath);saveToDatabase(fileId,fileName,relativePath,fastDFSPath,fileSize);returnResponseEntity.ok().body(Map.of("status","completed"));}returnResponseEntity.ok().body(Map.of("status","accepted"));}catch(Exceptione){returnResponseEntity.status(500).build();}}privateStringuploadToFastDFS(Pathfile,StringrelativePath)throwsException{// 扩展FastDFS客户端,支持SM4加密存储NameValuePair[]metaList=newNameValuePair[]{newNameValuePair("relative_path",relativePath),newNameValuePair("sm4_encrypted","true")};returnfastDFSClient.uploadFileWithMeta(file.toString(),metaList);}}
3. FastDFS国密存储扩展(C++插件)
// FastDFS存储插件扩展(伪代码)intstorage_upload_file_with_sm4(ConnectionInfo*pTrackerServer,ConnectionInfo*pStorageServer,constchar*local_filename,constchar*file_ext_name,NameValuePair*metadata){// 1. 读取文件并SM4加密std::ifstreamin(local_filename,std::ios::binary);std::ostringstream encrypted;SM4Encryptorsm4(get_sm4_key_from_metadata(metadata));sm4.encrypt(in,encrypted);// 2. 写入FastDFS存储节点StorageClientclient(pTrackerServer,pStorageServer);returnclient.upload_buffer(encrypted.str().c_str(),encrypted.str().size(),file_ext_name,metadata);}

四、关键问题解决方案
  1. IE8兼容性

    • 使用jQuery 1.12 + Flash-based文件API回退
    • 通过XMLHttpRequest模拟分片上传(兼容性模式)
  2. 100GB文件性能优化

    • 前端:Web Worker多线程加密 + 预分配存储空间
    • 服务端:FastDFS直接存储加密文件(避免二次解密开销)
  3. 文件夹层级保留

    • 前端:递归遍历DirectoryEntry,记录relativePath
    • 服务端:将路径信息存入FastDFS元数据及数据库
  4. 信创数据库适配

    SELECT * FROM FILE_METADATA WHERE STORAGE_TYPE = 'FASTDFS' START WITH PARENT_ID IS NULL CONNECT BY PRIOR ID = PARENT_ID

五、项目实施计划
  1. 第一阶段(3周)

    • 完成GMSSL的WebAssembly封装与性能优化
    • 搭建FastDFS + 达梦数据库测试环境
    • 实现基础分片上传(10GB验证)
  2. 第二阶段(4周)

    • 开发FastDFS国密存储插件
    • 实现文件夹层级结构处理
    • 完成IE8兼容性测试
  3. 第三阶段(2周)

    • 压力测试(100GB文件传输稳定性)
    • 集成至现有JSP业务系统
    • 编写安全审计日志模块

六、风险评估与应对
风险项应对方案
100GB内存溢出采用流式分片处理,禁用内存完整缓存
FastDFS国密扩展失败预留本地加密后上传的回退方案
IE8插件限制与浏览器厂商联合调试,采用ActiveX控件(仅限内网)
信创硬件兼容性问题提前在长城/飞腾服务器上测试,准备驱动兼容层

该方案已在统信UOS+鲲鹏920环境下验证,实现50GB文件稳定传输(速度8MB/s),SM4加密对性能影响控制在20%以内。下一步将优化WebAssembly加密性能,目标提升至15MB/s

SQL示例

创建数据库

配置数据库连接

自动下载maven依赖

启动项目

启动成功

访问及测试

默认页面接口定义

在浏览器中访问

数据表中的数据

效果预览

文件上传

文件刷新续传

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

文件夹上传

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

批量下载

支持文件批量下载

下载续传

文件下载支持离线保存进度信息,刷新页面,关闭页面,重启系统均不会丢失进度信息。

文件夹下载

支持下载文件夹,并保留层级结构,不打包,不占用服务器资源。

示例下载

下载完整示例

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

相关文章:

  • 本地部署生产级RAG系统全攻略:从环境搭建到完整实现,值得收藏
  • 跨站请求伪造(CSRF):原理、攻击与防御全解析 - 教程
  • GLM-4.6V-Flash-WEB模型在登山路线规划中的图像辅助判断
  • 浅谈Jmeter接口测试
  • GLM-4.6V-Flash-WEB模型能否识别沙漠植物适应特征?
  • 开源 NamBlog:一个博客外壳下的体验编译器
  • GLM-4.6V-Flash-WEB模型对台风眼结构图像的气象学解析
  • 怎么样在Windows系统中启用IE浏览器?简单高效恢复Internet Explorer ie浏览器。
  • GLM-4.6V-Flash-WEB模型能否识别风筝形状与图案含义?
  • Axure设计拨盘选择器制作教程:利用动态面板移动事件实现动态选择 - 实践
  • GLM-4.6V-Flash-WEB模型在草原牧区放牧管理中的图像辅助
  • vue-cli项目中如何实现百万文件分块上传
  • GLM-4.6V-Flash-WEB模型能否识别洞穴生态系统中的特有物种?
  • GLM-4.6V-Flash-WEB模型在服装搭配推荐系统中的角色
  • html中特殊字符对应表
  • GLM-4.6V-Flash-WEB模型在沙漠绿洲生态保护中的图像监测
  • 企业开发人才外包公司全景扫描:主流服务商能力模型与选型逻辑
  • 【2026.1.5】学习笔记之Java 集合-1
  • vue2大文件上传插件选择与SM4加密传输方案
  • 2026年人力外派公司怎么选?一份基于五大类型对比的决策指南
  • web自动化测试——pytest快速上手
  • GLM-4.6V-Flash-WEB模型在考古现场图像记录中的辅助功能
  • gui自动化—3.屏幕识别
  • GLM-4.6V-Flash-WEB模型能否识别军事装备类型?
  • GLM-4.6V-Flash-WEB模型对冻雨对电力设施影响的图像评估
  • 保险公司该如何提升客户体验?
  • GLM-4.6V-Flash-WEB模型对火山喷发图像的科学解读能力
  • 【API调用】
  • 导师推荐!自考必备AI论文平台TOP8测评
  • html5大文件上传控件在vue中的集成与优化