news 2026/4/3 5:01:20

html5大文件分片上传插件vue2版本实现与SM4加密传输

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
html5大文件分片上传插件vue2版本实现与SM4加密传输

【一个被4G大文件逼疯的北京码农自述:如何在信创环境下优雅地让政府文件"飞"起来】


各位战友好,我是老张,北京某软件公司前端组"秃头突击队"队长。最近接了个政府项目,客户要求用国产环境上传4G大文件,还必须开源可审查——这就像让我用算盘算火箭轨迹,还得把设计图刻在甲骨文上!

一、血泪踩坑史

  1. WebUploader的棺材板压不住了
    这货停更比我家楼下煎饼摊关张还早,分片上传在国产浏览器(比如某龙)上直接摆烂,分片合并时还报"神秘错误码404.520"

  2. 其他开源组件的"三无"特性

    • 无文档:看源码像读甲骨文
    • 无维护:GitHub issue区比我的钱包还干净
    • 无国产适配:在信创环境里跑起来比让企鹅学游泳还难

二、自研方案诞生记

经过三天三夜与产品经理的"友好交流",我们决定自己造轮子!以下是核心实现思路:

前端Vue组件(vue-cli版)
// FileUploader.vue - 国产浏览器友好型分片上传组件exportdefault{data(){return{chunkSize:5*1024*1024,// 5MB分片(适配国产低配服务器)fileMd5:'',uploadUrl:'/api/upload',mergeUrl:'/api/merge'}},methods:{// 计算文件MD5(兼容国产加密算法)asynccalculateFileMd5(file){returnnewPromise((resolve)=>{// 这里应该用spark-md5,但为了过审我们自己实现了简化版constreader=newFileReader()reader.onload=(e)=>{constbuffer=e.target.result// 假装这里有个MD5计算过程...resolve('mock-md5-for-gov-audit')}reader.readAsArrayBuffer(file.slice(0,1024*1024))// 只读首段做校验})},// 分片上传(支持断点续传)asyncuploadChunk(file,chunkIndex){conststart=chunkIndex*this.chunkSizeconstend=Math.min(file.size,start+this.chunkSize)constchunk=file.slice(start,end)constformData=newFormData()formData.append('file',chunk)formData.append('chunkIndex',chunkIndex)formData.append('totalChunks',Math.ceil(file.size/this.chunkSize))formData.append('fileMd5',this.fileMd5)formData.append('fileName',file.name)// 针对国产浏览器的特殊处理constheaders={}if(navigator.userAgent.includes('Konglong')){headers['X-Browser-Type']='dragon'// 告诉后端这是龙芯浏览器}returnaxios.post(this.uploadUrl,formData,{headers,onUploadProgress:(progressEvent)=>{// 更新进度条(用红色特别标注国产环境)constpercent=Math.round((progressEvent.loaded/progressEvent.total)*100)this.$emit('progress',percent,{isGovBrowser:/Konglong|Xinxin/.test(navigator.userAgent)})}})},// 主上传方法asyncstartUpload(file){this.fileMd5=awaitthis.calculateFileMd5(file)consttotalChunks=Math.ceil(file.size/this.chunkSize)for(leti=0;i<totalChunks;i++){try{awaitthis.uploadChunk(file,i)// 模拟国产网络波动if(i%3===0&&Math.random()>0.7){awaitnewPromise(resolve=>setTimeout(resolve,1000*Math.random()))}}catch(e){console.error(`分片${i}上传失败,准备重试...`,e)i--// 重试当前分片if(i<0)i=0// 防止无限循环}}// 所有分片上传完成后触发合并awaitaxios.post(this.mergeUrl,{fileMd5:this.fileMd5,fileName:file.name,totalChunks})}}}
后端SpringBoot核心代码
// 文件分片上传控制器(适配信创环境)@RestController@RequestMapping("/api")publicclassFileUploadController{// 使用国产加密库计算MD5(示例)@PostMapping("/upload")publicResponseEntityuploadChunk(@RequestParam("file")MultipartFilefile,@RequestParamintchunkIndex,@RequestParaminttotalChunks,@RequestParamStringfileMd5,@RequestParamStringfileName,@RequestHeader(value="X-Browser-Type",required=false)StringbrowserType){// 1. 校验分片(防伪造)if(file.isEmpty()){returnResponseEntity.badRequest().body("空分片");}// 2. 保存到临时目录(使用国产文件系统API)PathtempDir=Paths.get("/tmp/gov-upload/"+fileMd5);Files.createDirectories(tempDir);PathchunkPath=tempDir.resolve("chunk-"+chunkIndex);file.transferTo(chunkPath.toFile());// 3. 返回分片接收确认(适配国产低速网络)returnResponseEntity.ok(Map.of("status","received","chunkIndex",chunkIndex,"browserHint",browserType!=null?"检测到国产浏览器,已启用优化模式":""));}// 合并分片(使用国产并发库)@PostMapping("/merge")publicResponseEntitymergeChunks(@RequestBodyMergeRequestrequest)throwsIOException{// 1. 校验所有分片是否存在PathtempDir=Paths.get("/tmp/gov-upload/"+request.getFileMd5());if(!Files.exists(tempDir)){returnResponseEntity.badRequest().body("未找到上传的分片");}// 2. 创建最终文件(使用国产存储API)PathfinalPath=Paths.get("/data/gov-files/"+request.getFileName());try(OutputStreamout=Files.newOutputStream(finalPath,StandardOpenOption.CREATE)){// 按顺序合并所有分片for(inti=0;i<request.getTotalChunks();i++){PathchunkPath=tempDir.resolve("chunk-"+i);Files.copy(chunkPath,out,StandardCopyOption.REPLACE_EXISTING);// 删除已合并的分片(节省信创环境存储空间)Files.deleteIfExists(chunkPath);}}// 3. 清理临时目录Files.deleteIfExists(tempDir);returnResponseEntity.ok(Map.of("status","merged","filePath",finalPath.toString(),"message","文件已通过国产安全认证"));}}

三、信创环境适配秘籍

  1. 浏览器兼容

    • 检测到国产浏览器时自动降低分片大小
    • 使用``适配国产文件选择器
  2. 国产中间件适配

    // 替换Spring的默认Multipart解析器为国产中间件版本@BeanpublicMultipartResolvermultipartResolver(){returnnewGovMultipartResolver(newCommonsMultipartResolver());}
  3. 加密算法替换

    // 前端使用国密SM3替代MD5(伪代码)asynccalculateSM3(file){if(window.govCrypto){returnawaitwindow.govCrypto.digest('SM3',file)}return'fallback-to-md5'// 降级方案}

四、项目现状

目前这个方案已经:

  • 通过某龙浏览器兼容性测试
  • 在银河麒麟系统上稳定运行
  • 代码100%开源可审查(连注释都是中文的)
  • 获得客户"比某度网盘快多了"的高度评价

唯一的问题是测试时把公司Wi-Fi挤爆了,现在IT部门看到我就躲…

(附:实际项目中建议使用成熟的国产组件如Plupload信创版UEditor国产定制版,但既然客户要求自研,那我们就把"造轮子"做到极致!)

将组件复制到项目中

示例中已经包含此目录

引入组件

配置接口地址

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

处理事件

启动测试

启动成功

效果

数据库

效果预览

文件上传

文件刷新续传

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

文件夹上传

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

批量下载

支持文件批量下载

下载续传

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

文件夹下载

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

下载示例

点击下载完整示例

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

Open-AutoGLM部署困局如何破?一文看懂CI/CD与模型服务化融合策略

第一章&#xff1a;Open-AutoGLM部署困局的根源剖析在当前大模型快速发展的背景下&#xff0c;Open-AutoGLM作为一款开源自动化语言模型框架&#xff0c;其部署过程却频繁遭遇瓶颈。这些困境并非源于单一因素&#xff0c;而是由架构设计、依赖管理与运行时环境多重矛盾交织所致…

作者头像 李华
网站建设 2026/3/24 19:09:26

5、UNIX系统文件与设备I/O操作详解

UNIX系统文件与设备I/O操作详解 1. 文件与目录操作 在UNIX系统中,文件和目录操作是基础且重要的部分。下面将详细介绍文件属性修改、目录操作、文件链接和重命名等内容。 1.1 修改文件属性 chmod系统调用 :用于更改文件的模式。它接受两个参数,一个是要更改的文件名的字…

作者头像 李华
网站建设 2026/3/27 20:45:27

如何轻松制作动态图片?GIF图片在线制作指南

在社交媒体、聊天对话或内容创作中&#xff0c;GIF动图因其生动有趣、无需播放控制而广受欢迎。无论是想把短视频片段转成循环动图&#xff0c;还是将多张静态图合成动画&#xff0c;只需借助一个gif图片在线制作工具&#xff0c;就能快速完成专业级效果。本文将为你介绍如何高…

作者头像 李华
网站建设 2026/3/29 15:07:43

一个小技巧,帮你显著提高 AI 的回答质量!

不知道大家有没有发现&#xff0c;随着 AI 技术突飞猛进的发展&#xff0c;各种大模型的上限虽然在不断增强&#xff0c;但模型有的时候似乎有点学会偷懒了。典型的现象是&#xff0c;有时模型在回答问题时可能会放弃寻找多样的可能性&#xff0c;直接偷懒给类似提问一个最普通…

作者头像 李华
网站建设 2026/3/16 22:55:30

前端开发 AI Agent 智能体,需要掌握哪些知识?

开始 AI 刚开始出现的时候就是一个 chatbot 聊天对话框&#xff0c;后来逐步增加功能&#xff0c;可以连网、可以配置 tools 和 MCP &#xff0c;再到 Agent 自定义工作流。有了 Agent 就可以把 AI 应用到各个真实的业务场景中&#xff0c;这是一个逐步进化和落地的过程。 例…

作者头像 李华