news 2026/5/1 10:36:36

国密加密在大文件上传插件中的实现与优化

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
国密加密在大文件上传插件中的实现与优化

大文件传输方案设计与实现方案

作为湖南XX软件公司的前端工程师,面对20G大文件传输的需求,我经过深入调研和分析后提出以下解决方案。

一、技术挑战分析

  1. 大文件传输

    • 20G文件直接上传会导致内存溢出
    • 网络中断后需要支持断点续传
    • 传输进度监控和速度控制
  2. 浏览器兼容性

    • IE8不支持现代文件API(File API)
    • 老浏览器不支持WebSocket和Fetch API
    • 跨浏览器行为不一致问题
  3. 加密要求

    • 前端实现SM4和AES加密
    • 密钥安全管理和传输
  4. 文件夹结构保持

    • 需要设计合理的数据结构表示层级
    • 后端需要支持多级目录存储

二、整体架构设计

前端方案

用户界面

文件分片

加密模块

上传队列

断点续传控制

进度监控

文件夹解析

后端方案

接收分片

分片校验

合并文件

存储加密

数据库记录

文件元数据

三、前端核心实现

1. 文件分片上传基础代码

// file-uploader.jsclassFileUploader{constructor(options){this.chunkSize=options.chunkSize||5*1024*1024;// 默认5MBthis.maxRetry=options.maxRetry||3;this.concurrent=options.concurrent||3;this.encryptAlgorithm=options.encryptAlgorithm||'AES';}asyncupload(file){consttotalChunks=Math.ceil(file.size/this.chunkSize);constfileHash=awaitthis.calculateFileHash(file);// 检查服务端已上传分片const{uploadedChunks}=awaitthis.checkServerStatus(file.name,fileHash);constuploadQueue=[];for(leti=0;i<totalChunks;i++){if(!uploadedChunks.includes(i)){uploadQueue.push(this.uploadChunk(file,i,fileHash));}}awaitPromise.all(uploadQueue.slice(0,this.concurrent));awaitthis.mergeChunks(file.name,fileHash,totalChunks);}asyncuploadChunk(file,chunkIndex,fileHash){conststart=chunkIndex*this.chunkSize;constend=Math.min(file.size,start+this.chunkSize);constchunk=file.slice(start,end);// 加密处理constencryptedChunk=awaitthis.encrypt(chunk);constformData=newFormData();formData.append('file',encryptedChunk);formData.append('chunkIndex',chunkIndex);formData.append('totalChunks',Math.ceil(file.size/this.chunkSize));formData.append('fileHash',fileHash);for(letattempt=0;attempt<this.maxRetry;attempt++){try{awaitaxios.post('/api/upload',formData,{onUploadProgress:(progressEvent)=>{this.updateProgress(chunkIndex,progressEvent.loaded/progressEvent.total);}});return;}catch(error){if(attempt===this.maxRetry-1)throwerror;}}}asyncencrypt(data){if(this.encryptAlgorithm==='SM4'){returnsm4Encrypt(data,this.encryptionKey);}else{returnaesEncrypt(data,this.encryptionKey);}}}

2. IE8兼容方案

// ie8-compat.jsfunctionsetupIEFallback(){if(!window.File||!window.FileReader||!window.FileList||!window.Blob){// 使用Flash或ActiveX后备方案document.getElementById('file-input').outerHTML=`您的浏览器不支持文件上传功能`;}}

3. 文件夹上传实现

// folder-uploader.jsasyncfunctionuploadFolder(folderInput){constentries=awaitgetFolderEntries(folderInput);conststructure={};for(constentryofentries){constrelativePath=entry.webkitRelativePath;constpathParts=relativePath.split('/');letcurrentLevel=structure;for(leti=0;i<pathParts.length-1;i++){constpart=pathParts[i];if(!currentLevel[part]){currentLevel[part]={};}currentLevel=currentLevel[part];}if(entry.isFile){constfile=awaitgetFileFromEntry(entry);currentLevel[pathParts[pathParts.length-1]]=file;}}awaituploadFolderStructure(structure);}asyncfunctionuploadFolderStructure(structure,basePath=''){for(const[name,content]ofObject.entries(structure)){constcurrentPath=basePath?`${basePath}/${name}`:name;if(contentinstanceofFile){// 上传文件constuploader=newFileUploader();awaituploader.upload(content,currentPath);}else{// 创建目录并递归上传内容awaitaxios.post('/api/createFolder',{path:currentPath});awaituploadFolderStructure(content,currentPath);}}}

四、后端核心实现

1. 分片接收接口

// UploadController.java@RestController@RequestMapping("/api")publicclassUploadController{@PostMapping("/upload")publicResponseEntityuploadChunk(@RequestParam("file")MultipartFilefile,@RequestParam("chunkIndex")intchunkIndex,@RequestParam("totalChunks")inttotalChunks,@RequestParam("fileHash")StringfileHash){try{// 解密处理byte[]decryptedData=decrypt(file.getBytes(),getEncryptionKey());// 存储分片StringtempDir=getTempDir(fileHash);Files.createDirectories(Paths.get(tempDir));PathchunkPath=Paths.get(tempDir,String.valueOf(chunkIndex));Files.write(chunkPath,decryptedData);returnResponseEntity.ok().build();}catch(Exceptione){returnResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();}}@PostMapping("/merge")publicResponseEntitymergeChunks(@RequestParam("fileName")StringfileName,@RequestParam("fileHash")StringfileHash,@RequestParam("totalChunks")inttotalChunks){try{StringtempDir=getTempDir(fileHash);PathoutputPath=Paths.get(getStorageDir(),fileName);try(OutputStreamos=newFileOutputStream(outputPath.toFile())){for(inti=0;i<totalChunks;i++){PathchunkPath=Paths.get(tempDir,String.valueOf(i));byte[]chunkData=Files.readAllBytes(chunkPath);os.write(chunkData);}}// 存储加密encryptAndStore(outputPath,getStorageKey());// 清理临时分片FileUtils.deleteDirectory(newFile(tempDir));returnResponseEntity.ok().build();}catch(Exceptione){returnResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();}}}

2. 文件夹结构存储设计

// FileEntity.java@Entity@Table(name="file_storage")publicclassFileEntity{@Id@GeneratedValue(strategy=GenerationType.IDENTITY)privateLongid;privateStringname;privateStringpath;// 完整路径如 /folder/subfolder/file.txtprivatebooleanisDirectory;privateLongparentId;// 父目录IDprivateStringstorageKey;// 物理存储键privateStringencryptionAlgorithm;// SM4/AESprivateStringchecksum;privatelongsize;// 关系映射@OneToMany@JoinColumn(name="parentId")privateListchildren;// Getters and setters...}

3. 加密服务实现

// EncryptionService.java@ServicepublicclassEncryptionService{publicbyte[]encrypt(byte[]data,Stringalgorithm,Stringkey){if("SM4".equalsIgnoreCase(algorithm)){returnSM4Util.encrypt(data,key);}else{returnAESUtil.encrypt(data,key);}}publicbyte[]decrypt(byte[]data,Stringalgorithm,Stringkey){if("SM4".equalsIgnoreCase(algorithm)){returnSM4Util.decrypt(data,key);}else{returnAESUtil.decrypt(data,key);}}}

五、数据库设计

CREATETABLEfile_storage(idBIGINTPRIMARYKEYAUTO_INCREMENT,nameVARCHAR(255)NOTNULL,pathVARCHAR(1024)NOTNULL,is_directoryBOOLEANNOTNULL,parent_idBIGINT,storage_keyVARCHAR(255),encryption_algorithmVARCHAR(10),checksumVARCHAR(64),sizeBIGINT,created_atTIMESTAMPDEFAULTCURRENT_TIMESTAMP,updated_atTIMESTAMPDEFAULTCURRENT_TIMESTAMPONUPDATECURRENT_TIMESTAMP,FOREIGNKEY(parent_id)REFERENCESfile_storage(id));CREATEINDEXidx_file_pathONfile_storage(path);CREATEINDEXidx_file_parentONfile_storage(parent_id);

六、部署与优化建议

  1. 前端优化

    • 使用Web Worker处理加密计算,避免UI阻塞
    • 实现自适应分片大小,根据网络质量动态调整
    • 添加本地存储记录,支持页面刷新后恢复上传
  2. 后端优化

    • 使用Nginx进行负载均衡和文件上传代理
    • 实现分布式文件存储,支持水平扩展
    • 添加Redis缓存已上传分片信息
  3. 安全建议

    • 实现密钥轮换机制
    • 添加文件完整性校验
    • 限制单个IP的上传速度和并发数

七、测试方案

  1. 单元测试

    • 分片功能测试
    • 加密/解密测试
    • 文件夹结构解析测试
  2. 集成测试

    • 跨浏览器测试
    • 大文件(20G+)传输测试
    • 断网恢复测试
  3. 性能测试

    • 并发上传测试
    • 网络限速环境测试
    • 服务器资源占用监控

此方案综合了现代Web技术和传统浏览器兼容性需求,采用分片上传、断点续传和加密传输等核心技术,能够满足20G大文件传输的需求,同时保持文件夹结构和跨平台兼容性。

设置框架

安装.NET Framework 4.7.2
https://dotnet.microsoft.com/en-us/download/dotnet-framework/net472
框架选择4.7.2

添加3rd引用

编译项目

NOSQL

NOSQL无需任何配置可直接访问页面进行测试

SQL

使用IIS
大文件上传测试推荐使用IIS以获取更高性能。

使用IIS Express

小文件上传测试可以使用IIS Express

创建数据库

配置数据库连接信息

检查数据库配置

访问页面进行测试


相关参考:
文件保存位置,

效果预览

文件上传

文件刷新续传

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

文件夹上传

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

下载完整示例

下载完整示例

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

Jupyter Notebook分栏显示PyTorch代码与输出

Jupyter Notebook 分栏显示 PyTorch 代码与输出 在高分辨率显示器普及的今天&#xff0c;开发者却仍在为“写一行代码、滚三屏看结果”而烦恼。尤其是在深度学习实验中&#xff0c;一个训练循环的日志动辄上百行&#xff0c;图像生成结果藏在文档底部&#xff0c;调试时来回翻…

作者头像 李华
网站建设 2026/5/1 5:02:45

Spring Boot 校园综合服务

Spring Boot 校园综合服务介绍 在现代校园生活节奏日益加快、师生需求愈发多元化的当下&#xff0c;Spring Boot 校园综合服务系统宛如一位万能助手&#xff0c;全方位覆盖校园学习、生活、社交等各个领域&#xff0c;依托 Spring Boot 强大的开发框架&#xff0c;将繁杂事务化…

作者头像 李华
网站建设 2026/5/1 5:06:35

SSH公钥认证配置:告别重复输入密码

SSH公钥认证配置&#xff1a;告别重复输入密码 在现代深度学习与AI开发中&#xff0c;工程师常常需要频繁连接远程GPU服务器执行训练任务。无论是调试模型、监控显存使用&#xff0c;还是批量部署推理服务&#xff0c;SSH都是最常用的接入方式。然而&#xff0c;每次输入密码不…

作者头像 李华
网站建设 2026/5/1 5:52:52

【企业管理】企业关键角色多维深度特征分析

企业关键角色多维深度特征分析表维度类别高层管理者 (CXO/VP)中层管理者 (总监/经理)基层员工 (专员/骨干)职能支持人员 (HR/财务/行政)核心技术人员 (研发/工程师)销售与市场人员1. 需求类型​核心需求企业永续经营、战略目标实现、资本回报最大化、个人历史定位与行业声望。部…

作者头像 李华