vue大文件上传的示例代码与源码解析分享

大文件传输系统设计方案(基于SM4国密算法)

需求分析

作为四川某软件公司的开发人员,我面临以下核心需求:

  1. 实现10GB级别大文件的分片上传/下载
  2. 采用国密SM4算法进行端到端加密
  3. 服务端需支持SM4加密存储
  4. 兼容主流浏览器及信创国产化环境
  5. 基于SpringBoot+Vue技术栈
  6. 需要开源可审查的代码

技术选型

经过调研,我决定采用以下技术方案:

前端方案

  • 基于Vue-cli构建
  • 使用自定义分片上传组件(替代已停更的WebUploader)
  • 集成SM4加密的JavaScript实现(通过wasm或纯JS实现)

后端方案

  • SpringBoot 2.7.x
  • 集成BouncyCastle的SM4实现
  • 支持分片合并和加密存储

前端核心代码实现

1. SM4加密工具类 (sm4-utils.js)

// 使用wasm版本的SM4实现(性能更好)letsm4Module=null;exportasyncfunctioninitSM4(){if(sm4Module)return;try{sm4Module=awaitimport('sm4-wasm');awaitsm4Module.default();// 初始化wasm模块}catch(e){console.error('SM4 WASM加载失败,降级使用JS实现',e);// 降级方案:使用纯JS实现awaitimport('./sm4-js').then(module=>{sm4Module=module;});}}exportfunctionencryptFileChunk(chunk,key,iv){if(!sm4Module)thrownewError('SM4未初始化');// 转换为ArrayBufferconstarrayBuffer=chunkinstanceofArrayBuffer?chunk:awaitnewResponse(chunk).arrayBuffer();// 使用SM4-CBC模式加密returnsm4Module.encrypt(arrayBuffer,key,iv,'CBC');}exportfunctiondecryptFileChunk(encryptedChunk,key,iv){if(!sm4Module)thrownewError('SM4未初始化');returnsm4Module.decrypt(encryptedChunk,key,iv,'CBC');}

2. 分片上传组件 (FileUploader.vue)

import{initSM4,encryptFileChunk}from'./sm4-utils';// 生成随机IVfunctiongenerateIV(){returncrypto.getRandomValues(newUint8Array(16));}exportdefault{data(){return{file:null,uploading:false,progress:0,chunkSize:5*1024*1024,// 5MB每片sm4Key:null,// 实际应从安全渠道获取fileId:null};},asyncmounted(){awaitinitSM4();// 生成随机密钥(实际项目应从安全渠道获取)this.sm4Key=crypto.getRandomValues(newUint8Array(16));},methods:{handleFileChange(e){this.file=e.target.files[0];this.progress=0;},asyncstartUpload(){if(!this.file)return;this.uploading=true;this.progress=0;try{// 1. 初始化上传,获取fileIdconstinitRes=awaitthis.$http.post('/api/upload/init',{fileName:this.file.name,fileSize:this.file.size,chunkSize:this.chunkSize});this.fileId=initRes.data.fileId;constiv=generateIV();// 2. 上传加密分片constchunkCount=Math.ceil(this.file.size/this.chunkSize);letuploadedChunks=0;for(leti=0;i<chunkCount;i++){conststart=i*this.chunkSize;constend=Math.min(start+this.chunkSize,this.file.size);constchunk=this.file.slice(start,end);// 加密分片constencryptedChunk=awaitencryptFileChunk(chunk,this.sm4Key,iv);// 上传分片constformData=newFormData();formData.append('fileId',this.fileId);formData.append('chunkIndex',i);formData.append('chunk',newBlob([encryptedChunk]));formData.append('iv',newBlob([iv]));// 每个分片使用相同IV(简单实现)awaitthis.$http.post('/api/upload/chunk',formData,{headers:{'Content-Type':'multipart/form-data'}});uploadedChunks++;this.progress=Math.floor((uploadedChunks/chunkCount)*100);}// 3. 完成上传awaitthis.$http.post('/api/upload/complete',{fileId:this.fileId,iv:Array.from(iv).join(',')// 实际应使用更安全的方式传输IV});this.$emit('upload-success',{fileId:this.fileId,fileName:this.file.name});}catch(error){console.error('上传失败:',error);this.$emit('upload-error',error);}finally{this.uploading=false;}}}};

后端核心代码实现

1. SM4工具类 (SM4Util.java)

importorg.bouncycastle.crypto.engines.SM4Engine;importorg.bouncycastle.crypto.modes.CBCBlockCipher;importorg.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;importorg.bouncycastle.crypto.params.KeyParameter;importorg.bouncycastle.crypto.params.ParametersWithIV;importorg.bouncycastle.jce.provider.BouncyCastleProvider;importjavax.crypto.Cipher;importjavax.crypto.spec.SecretKeySpec;importjava.security.Security;importjava.util.Base64;publicclassSM4Util{static{Security.addProvider(newBouncyCastleProvider());}// 加密文件分片publicstaticbyte[]encrypt(byte[]key,byte[]iv,byte[]input)throwsException{PaddedBufferedBlockCiphercipher=newPaddedBufferedBlockCipher(newCBCBlockCipher(newSM4Engine()));cipher.init(true,newParametersWithIV(newKeyParameter(key),iv));byte[]output=newbyte[cipher.getOutputSize(input.length)];intlen=cipher.processBytes(input,0,input.length,output,0);len+=cipher.doFinal(output,len);if(len<output.length){byte[]result=newbyte[len];System.arraycopy(output,0,result,0,len);returnresult;}returnoutput;}// 解密文件分片publicstaticbyte[]decrypt(byte[]key,byte[]iv,byte[]input)throwsException{PaddedBufferedBlockCiphercipher=newPaddedBufferedBlockCipher(newCBCBlockCipher(newSM4Engine()));cipher.init(false,newParametersWithIV(newKeyParameter(key),iv));byte[]output=newbyte[cipher.getOutputSize(input.length)];intlen=cipher.processBytes(input,0,input.length,output,0);len+=cipher.doFinal(output,len);if(len<output.length){byte[]result=newbyte[len];System.arraycopy(output,0,result,0,len);returnresult;}returnoutput;}// 使用JCE方式(备选方案)publicstaticbyte[]encryptJCE(byte[]key,byte[]iv,byte[]input)throwsException{Ciphercipher=Cipher.getInstance("SM4/CBC/PKCS5Padding","BC");SecretKeySpeckeySpec=newSecretKeySpec(key,"SM4");cipher.init(Cipher.ENCRYPT_MODE,keySpec,newjavax.crypto.spec.IvParameterSpec(iv));returncipher.doFinal(input);}}

2. 文件上传控制器 (FileUploadController.java)

importorg.springframework.beans.factory.annotation.Value;importorg.springframework.web.bind.annotation.*;importorg.springframework.web.multipart.MultipartFile;importjava.io.File;importjava.io.FileOutputStream;importjava.nio.file.Files;importjava.nio.file.Paths;importjava.util.Base64;importjava.util.UUID;importjava.util.concurrent.ConcurrentHashMap;@RestController@RequestMapping("/api/upload")publicclassFileUploadController{@Value("${file.upload-dir}")privateStringuploadDir;// 临时存储上传状态privatefinalConcurrentHashMapsessions=newConcurrentHashMap<>();// 初始化上传@PostMapping("/init")publicUploadInitResponseinitUpload(@RequestBodyUploadInitRequestrequest){StringfileId=UUID.randomUUID().toString();UploadSessionsession=newUploadSession();session.setFileName(request.getFileName());session.setTotalSize(request.getFileSize());session.setChunkSize(request.getChunkSize());session.setReceivedChunks(0);sessions.put(fileId,session);// 创建临时目录newFile(uploadDir+"/"+fileId).mkdirs();returnnewUploadInitResponse(fileId);}// 上传分片@PostMapping("/chunk")publicvoiduploadChunk(@RequestParam("fileId")StringfileId,@RequestParam("chunkIndex")intchunkIndex,@RequestParam("chunk")MultipartFilechunkFile,@RequestParam("iv")StringivBase64)throwsException{UploadSessionsession=sessions.get(fileId);if(session==null){thrownewRuntimeException("无效的上传会话");}// 解密分片(实际项目中密钥应从安全渠道获取)byte[]key=hexStringToByteArray("你的SM4密钥16字节");// 示例,实际应从配置或安全存储获取byte[]iv=Base64.getDecoder().decode(ivBase64);byte[]encryptedChunk=chunkFile.getBytes();byte[]decryptedChunk=SM4Util.decrypt(key,iv,encryptedChunk);// 保存分片StringchunkPath=uploadDir+"/"+fileId+"/"+chunkIndex;try(FileOutputStreamfos=newFileOutputStream(chunkPath)){fos.write(decryptedChunk);}session.setReceivedChunks(session.getReceivedChunks()+1);}// 完成上传@PostMapping("/complete")publicUploadCompleteResponsecompleteUpload(@RequestBodyUploadCompleteRequestrequest)throwsException{StringfileId=request.getFileId();UploadSessionsession=sessions.get(fileId);if(session==null){thrownewRuntimeException("无效的上传会话");}// 合并分片StringtempDir=uploadDir+"/"+fileId;StringfinalPath=uploadDir+"/"+fileId+".enc";// 加密存储try(FileOutputStreamfos=newFileOutputStream(finalPath)){for(inti=0;i<session.getTotalChunks();i++){byte[]chunk=Files.readAllBytes(Paths.get(tempDir+"/"+i));fos.write(chunk);}}// 清理临时文件Files.walk(Paths.get(tempDir)).sorted((a,b)->b.compareTo(a))// 反向排序先删文件再删目录.forEach(path->{try{Files.delete(path);}catch(Exceptione){// 记录日志}});// 存储文件元信息(实际项目应存入数据库)FileMetameta=newFileMeta();meta.setFileId(fileId);meta.setOriginalName(session.getFileName());meta.setEncryptedPath(finalPath);meta.setSize(session.getTotalSize());// 这里应该将meta保存到数据库returnnewUploadCompleteResponse(fileId,session.getFileName());}// 计算总分片数privateintcalculateTotalChunks(longfileSize,intchunkSize){return(int)Math.ceil((double)fileSize/chunkSize);}// 内部类定义省略...}

信创环境兼容性考虑

  1. 前端兼容性

    • 提供wasm和纯JS两套SM4实现,wasm优先
    • 使用标准的Web API,避免使用实验性功能
    • 测试环境包括:麒麟OS+飞腾CPU、UOS+龙芯等组合
  2. 后端兼容性

    • 使用BouncyCastle作为密码学提供者,兼容国产CPU指令集
    • 避免使用与特定JDK版本绑定的API
    • 测试环境包括:中科方德JDK、华为Kunpeng JDK等

安全考虑

  1. 密钥管理

    • 示例中简化了密钥处理,实际项目应:
    • 使用硬件加密机或软HSM管理主密钥
    • 每个文件使用随机生成的密钥,通过主密钥加密后传输
    • 考虑使用国密SSL/TLS (GMTLS)
  2. 传输安全

    • 所有通信必须通过HTTPS
    • 考虑使用双向SSL认证
  3. 存储安全

    • 服务端存储的是加密后的文件
    • 只有授权用户才能获取解密密钥

性能优化建议

  1. 前端可实现断点续传,记录已上传分片
  2. 后端可使用异步处理合并分片操作
  3. 对于超大文件,考虑使用更高效的存储格式
  4. 实现分片校验机制,确保数据完整性

总结

本方案提供了完整的SM4加密大文件传输实现,从前端分片加密到后端存储都符合国密要求。代码结构清晰,便于进行源代码审查。虽然实现起来比使用现成组件复杂,但完全可控且符合政府单位的安全要求。

下一步工作建议:

  1. 完善密钥管理方案
  2. 增加下载功能实现
  3. 添加更完善的错误处理和日志
  4. 进行全面的性能测试和安全审计

将组件复制到项目中

示例中已经包含此目录

引入组件

配置接口地址

接口地址分别对应:文件初始化,文件数据上传,文件进度,文件上传完毕,文件删除,文件夹初始化,文件夹删除,文件列表
参考:http://www.ncmem.com/doc/view.aspx?id=e1f49f3e1d4742e19135e00bd41fa3de

处理事件

启动测试

启动成功

效果

数据库

效果预览

文件上传

文件刷新续传

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

文件夹上传

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

批量下载

支持文件批量下载

下载续传

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

文件夹下载

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

下载示例

点击下载完整示例

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1118521.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一站式指南:盐雾腐蚀试验箱选购、品牌对比与厂家推荐 - 品牌推荐大师

在材料研发、质量控制及产品可靠性测试领域,盐雾腐蚀试验箱是评估金属、涂层、电镀件及复合材料耐腐蚀性能的核心设备。其通过模拟海洋或含盐潮湿环境,加速材料腐蚀过程,为改进工艺和提升产品质量提供关键数据。随着…

新手如何快速制作GIF?GIF制作指南

在日常分享中&#xff0c;生动有趣的GIF总能比静态图片更抓眼球&#xff0c;不管是记录生活片段、制作工作表情包&#xff0c;还是给文案搭配动态素材&#xff0c;gif制作都是绝佳选择。其实不用复杂的专业软件&#xff0c;新手也能快速做出高质量GIF&#xff0c;下面就把详细步…

Cilium监控日志无从下手?10个关键配置让你秒变专家

第一章&#xff1a;Cilium监控日志的核心价值与挑战在云原生环境中&#xff0c;网络可见性是保障系统稳定性和安全性的关键。Cilium 作为基于 eBPF 技术的高性能网络和安全解决方案&#xff0c;提供了深度的网络流量洞察能力。其监控日志不仅记录了 Pod 间的通信行为&#xff0…

大学生自学算法的好帮手:VibeThinker辅助理解DP与贪心

大学生自学算法的好帮手&#xff1a;VibeThinker辅助理解DP与贪心 在准备信息学竞赛或刷LeetCode的深夜&#xff0c;你是否曾面对一道动态规划题无从下手&#xff1f;状态怎么定义、转移方程如何写、边界条件又该怎样处理——这些问题往往让初学者望而却步。传统搜索引擎给出的…

如何借助在线制作gif动图?GIF在线制作攻略

在社交媒体分享、日常聊天互动或是工作汇报中&#xff0c;生动鲜活的GIF图总能自带“吸睛buff”&#xff0c;比静态图片更能精准传递情绪、展现细节。但提到GIF制作&#xff0c;不少人会误以为需要复杂的专业软件和设计功底。其实&#xff0c;借助gif图片在线制作工具&#xff…

基于多技术栈融合的婚恋交友系统设计与实现——以LINK婚恋系统为例

摘要&#xff1a;本文详细阐述了基于SpringBoot、MybatisPlus、Shiro、Netty、WebSocket、RabbitMQ、jwt、Redis、Vue3、Uniapp等多技术栈融合的LINK婚恋交友项目的系统设计与实现。通过对系统功能、技术特点、架构设计等方面的深入剖析&#xff0c;展示了该系统在婚恋交友领域…

发票查验接口详细接收参数说明-C#语言集成完整示例-API高效财税管理方案

发票是企业经营活动中核心的财务凭证之一&#xff0c;其真伪核验、信息提取与合规管理直接影响企业的税务风险控制与运营效率。在数字化转型浪潮下&#xff0c;企业对税务自动化、智能化的需求日益迫切。对此&#xff0c;发票查验接口应运而生&#xff0c;可实现一站式、高可靠…

2025年主流数据库PostgreSQL、MySQL、Oracle、MongoDB全景解析:技术选型与替代方案深度研究

引言 在数字化转型加速的2025年&#xff0c;数据库技术已从单一存储工具演变为企业核心竞争力的基石。从金融级分布式系统到实时物联网监控&#xff0c;从结构化交易处理到非结构化日志分析&#xff0c;数据库的架构选择直接影响业务效率与成本。本文将深度解析PostgreSQL、My…

自动化测试脚本生成:基于自然语言描述转换为可执行代码

自动化测试脚本生成&#xff1a;从自然语言到可执行代码的智能跃迁 在现代软件交付节奏日益紧凑的今天&#xff0c;一个新功能上线前最让人焦虑的环节是什么&#xff1f;不是编码&#xff0c;也不是部署——而是测试。尤其是当开发人员写完核心逻辑后&#xff0c;面对“请为这个…

Top-k采样设置建议:保持确定性同时避免死循环

Top-k采样设置建议&#xff1a;保持确定性同时避免死循环 在当前大模型推理的实际部署中&#xff0c;一个常被低估却至关重要的细节浮出水面——解码策略的微调&#xff0c;往往比模型本身的选择更能决定输出质量。尤其对于像 VibeThinker-1.5B-APP 这类专注于高强度逻辑任务的…

FastStone Capture注册码免费替代:用VibeThinker自动生成技术文档截图说明

VibeThinker-1.5B-APP&#xff1a;用小模型自动生成技术文档截图说明 在撰写开发教程、编写算法讲义或制作内部技术分享材料时&#xff0c;你是否也曾为“如何给一张代码截图配上清晰准确的解释”而反复修改&#xff1f;传统方式中&#xff0c;我们依赖手动标注工具&#xff08…

Docker Compose网络配置十大最佳实践,第7条至关重要

第一章&#xff1a;Docker Compose网络配置概述在使用 Docker Compose 编排多容器应用时&#xff0c;网络配置是实现服务间通信的核心环节。合理的网络设置能够确保容器之间安全、高效地交换数据&#xff0c;同时隔离不必要的访问。默认网络行为 Docker Compose 会为每个项目自…

2026年,面向hr总监的hr saas前10品牌榜整理分享!

回望 2025 年&#xff0c;中国 HR SaaS 行业正式告别 “野蛮生长”&#xff0c;迈入 “精耕细作” 的价值深化阶段。据艾瑞咨询、IDC两大权威机构年终数据显示&#xff0c;2025年行业市场规模突破260亿元&#xff0c;年复合增长率稳定保持在25%以上&#xff0c;数字化已从 HR 部…

智能家居中枢升级:从响应命令到主动推理用户意图

智能家居中枢升级&#xff1a;从响应命令到主动推理用户意图 在智能音箱能听懂“开灯”“调温”的今天&#xff0c;我们是否还满足于这种“指令-执行”的简单交互&#xff1f;当用户说&#xff1a;“我明天要早起开会&#xff0c;但现在很累&#xff0c;该怎么安排睡眠&#xf…

(Docker健康检查避坑手册)运维老炮儿绝不外传的6条军规

第一章&#xff1a;Docker健康检查避坑手册导论在现代容器化部署中&#xff0c;应用的稳定性与服务的自愈能力至关重要。Docker健康检查&#xff08;HEALTHCHECK&#xff09;机制为容器提供了判断内部进程是否正常运行的能力&#xff0c;是实现高可用架构的基础组件之一。合理配…

知乎专栏深度解读:拆解VibeThinker的技术创新点

VibeThinker-1.5B&#xff1a;小模型如何在数学与编程推理中实现“超车”&#xff1f; 当整个AI社区还在为千亿参数大模型的军备竞赛推波助澜时&#xff0c;一个仅15亿参数的轻量级模型悄然登场&#xff0c;并在多个高难度推理任务中击败了比它大数百倍的对手——这听起来像科幻…

面向未来的轻量化趋势:小模型将成为边缘计算主力

面向未来的轻量化趋势&#xff1a;小模型将成为边缘计算主力 在移动设备越来越智能、IoT终端日益密集的今天&#xff0c;一个现实问题正摆在开发者面前&#xff1a;我们真的需要把千亿参数的大模型塞进手机、嵌入式盒子甚至教室里的学习平板吗&#xff1f;当一次推理动辄消耗数…

模型即服务(MaaS)落地场景:VibeThinker作为核心组件

模型即服务&#xff08;MaaS&#xff09;落地场景&#xff1a;VibeThinker作为核心组件 在AI模型越来越“卷”参数的今天&#xff0c;一个仅15亿参数的小模型却悄悄登顶多项高强度推理榜单——微博开源的 VibeThinker-1.5B-APP 正是这样一个反直觉的存在。它没有试图成为通用对…

2026年红色主题展厅设计公司排名:盛世笔特集团市场口碑如何? - mypinpai

在红色文化传承与建教育阵地建设的浪潮中,选择一家专业的红色主题展厅设计公司至关重要。面对市场上众多的选择,如何辨别哪家公司口碑更好、实力更强?以下为你带来2025年红色主题展厅设计领域的优质公司排名,并深入…

API文档智能解析:VibeThinker提取关键参数与调用规则

API文档智能解析&#xff1a;VibeThinker提取关键参数与调用规则 在现代软件开发中&#xff0c;API集成已成为日常工作的核心环节。无论是对接第三方支付、调用云服务接口&#xff0c;还是构建微服务架构&#xff0c;开发者都不可避免地要面对大量非结构化、格式混乱的API文档。…