news 2026/6/20 5:59:15

SpringBoot大附件上传是否支持SM4加密传输与国密标准

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SpringBoot大附件上传是否支持SM4加密传输与国密标准

项目技术方案:大文件传输系统(企业级高可用方案)
编制:北京某互联网企业 前端研发部 - 张工
日期:2023年11月28日


一、项目背景与核心痛点

公司承接政府/军工领域项目,需开发50GB级文件传输系统,现有开源方案存在以下问题:

  1. WebUploader:已停更,IE兼容性差(需Flash),无技术支持
  2. Uppy/Plupload:现代浏览器支持好,但IE11需polyfill,无军工级稳定性保障
  3. 商业授权:单套授权成本高(约$5k/年),200+项目部署成本不可控

核心需求

  • 支持50GB文件分片传输(文件夹保留层级结构)
  • 断点续传(跨浏览器会话持久化)
  • 兼容IE11/Chrome/Firefox/360安全浏览器(兼容模式)
  • 私有化部署(内网环境)
  • 提供完整源代码(避免授权风险)

二、技术选型与架构设计

1. 前端架构(Vue3 + 兼容层)

Vue3主应用

文件选择器

分片上传控制器

进度持久化服务

WebDAV文件夹解析

加密传输模块

IndexedDB+Cookie双存储

关键组件

  • 文件夹解析:基于WebDAV协议解析本地文件夹结构(兼容IE11)
  • 分片引擎:动态调整分片大小(5MB-50MB自适应网络)
  • 持久化存储
    • 优先使用IndexedDB(存储分片元数据)
    • 降级使用Cookie(存储关键进度信息,兼容IE11)
2. 后端架构(SpringBoot微服务)
// 文件分片服务接口示例@RestController@RequestMapping("/api/upload")publicclassFileUploadController{@PostMapping("/init")publicResponseEntityinitUpload(@RequestParamStringfileName,@RequestParamlongfileSize,@RequestParamStringrelativePath){// 生成唯一任务ID(UUID v4)StringtaskId=UUID.randomUUID().toString();// 存储元数据到数据库(适配MySQL/Oracle/SQLServer)fileMetaService.save(taskId,fileName,fileSize,relativePath);returnResponseEntity.ok(taskId);}@PostMapping("/chunk")publicResponseEntityuploadChunk(@RequestParamStringtaskId,@RequestParamintchunkIndex,@RequestParamStringchunkHash,@RequestBodybyte[]chunkData){// 校验分片完整性(SHA-256)StringcomputedHash=DigestUtils.sha256Hex(chunkData);if(!computedHash.equals(chunkHash)){thrownewRuntimeException("分片校验失败");}// 存储分片到临时目录PathtempPath=Paths.get("/tmp/upload/"+taskId+"/"+chunkIndex);Files.write(tempPath,chunkData);// 更新数据库分片状态chunkStatusService.markUploaded(taskId,chunkIndex);returnResponseEntity.ok().build();}}

三、核心代码实现

1. 文件夹上传(Vue3组件)
import { ref, onMounted } from 'vue'; import { useIndexedDB } from './useIndexedDB'; // 自定义IndexedDB Hook import { sha256 } from 'js-sha256'; const fileInput = ref(null); const progress = ref(0); const { db, addTask, getTask } = useIndexedDB('fileUploadDB'); // 解析文件夹结构(兼容IE11) const parseFolder = (files) => { const tree = {}; Array.from(files).forEach(file => { const pathParts = file.webkitRelativePath.split('/'); let current = tree; pathParts.forEach((part, index) => { if (index === pathParts.length - 1) { current[part] = { file, path: file.webkitRelativePath, size: file.size }; } else { if (!current[part]) current[part] = {}; current = current[part]; } }); }); return tree; }; // 初始化上传任务 const initUploadTask = async (fileTree) => { const flatFiles = flattenFileTree(fileTree); const taskId = crypto.randomUUID(); // 存储到IndexedDB await addTask({ taskId, files: flatFiles, status: 'pending', createdAt: new Date() }); return taskId; }; // 分片上传逻辑 const uploadChunk = async (taskId, file, chunkIndex, chunkSize) => { const start = chunkIndex * chunkSize; const end = Math.min(file.size, start + chunkSize); const chunk = file.slice(start, end); // 计算分片哈希(用于校验) const chunkHash = sha256(chunk); try { const response = await fetch(`/api/upload/chunk`, { method: 'POST', headers: { 'Content-Type': 'application/octet-stream', 'X-Task-ID': taskId, 'X-Chunk-Index': chunkIndex.toString(), 'X-Chunk-Hash': chunkHash }, body: chunk }); if (!response.ok) throw new Error('上传失败'); // 更新本地进度 const task = await getTask(taskId); task.uploadedChunks.add(chunkIndex); await addTask(task); // 计算总体进度 const totalChunks = Math.ceil(file.size / chunkSize); const fileProgress = (task.uploadedChunks.size / totalChunks) * 100; // 更新全局进度(按文件大小加权) updateGlobalProgress(task, fileProgress); } catch (error) { console.error('分片上传失败:', error); throw error; } };
2. 断点续传持久化(IndexedDB + Cookie)
// useIndexedDB.js - 自定义HookexportfunctionuseIndexedDB(dbName){letdbInstance=null;constinitDB=async()=>{returnnewPromise((resolve,reject)=>{constrequest=indexedDB.open(dbName,2);request.onupgradeneeded=(e)=>{constdb=e.target.result;if(!db.objectStoreNames.contains('tasks')){db.createObjectStore('tasks',{keyPath:'taskId'});}};request.onsuccess=(e)=>{dbInstance=e.target.result;resolve(dbInstance);};request.onerror=(e)=>reject(e.target.error);});};constaddTask=async(task)=>{if(!dbInstance)awaitinitDB();returnnewPromise((resolve,reject)=>{consttx=dbInstance.transaction('tasks','readwrite');conststore=tx.objectStore('tasks');constrequest=store.put(task);request.onsuccess=()=>{// 同步关键信息到Cookie(IE11兼容)setCookie(`upload_task_${task.taskId}`,JSON.stringify({taskId:task.taskId,fileName:task.files[0]?.name,progress:calculateProgress(task)}),30);resolve();};request.onerror=reject;});};return{db:dbInstance,addTask,getTask};}// Cookie兼容层(IE11)functionsetCookie(name,value,days){letexpires='';if(days){constdate=newDate();date.setTime(date.getTime()+(days*24*60*60*1000));expires=`; expires=${date.toUTCString()}`;}document.cookie=`${name}=${value||''}${expires}; path=/`;}

四、兼容性解决方案

1. 浏览器兼容性矩阵
浏览器最低版本关键兼容方案
Chrome80+原生支持
Firefox78+原生支持
IE1111使用IndexedDB polyfill + Flash回退
360安全浏览器10+兼容模式识别(User-Agent检测)
2. IE11降级方案

五、部署与维护方案

  1. 私有化部署包

    • 提供Docker镜像(多架构支持)
    • 包含数据库初始化脚本(MySQL/Oracle/SQLServer)
  2. 维护策略

    • 建立内部维护团队(3人核心组)
    • 每月进行压力测试(50GB文件传输稳定性验证)
  3. 成本估算

    • 自研成本:约15人月(含测试)
    • 长期维护成本:每年约20万元(人力+服务器)

下一步行动建议

  1. 组建专项小组(前端2人 + 后端1人 + 测试1人)
  2. 采购基础版商业组件(如Plupload企业版)作为技术参考
  3. 搭建测试环境(IE11 + Windows Server 2016)

(签名:北京某互联网企业 前端架构师 张工)
联系方式:zhang.gong@company.com | 延伸阅读:《大文件传输系统性能优化白皮书》

导入项目

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

工程

NOSQL

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

创建数据表

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

修改数据库连接信息

访问页面进行测试

文件存储路径

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

效果预览

文件上传

文件刷新续传

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

文件夹上传

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

下载示例

点击下载完整示例

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

Python Flask封装HunyuanOCR API:构建轻量级微服务模块

Python Flask封装HunyuanOCR API:构建轻量级微服务模块 在智能文档处理需求日益增长的今天,企业对高效、准确且易于集成的OCR能力提出了更高要求。传统OCR系统往往依赖检测、识别、抽取等多个独立模型串联工作,架构复杂、部署成本高、响应延…

作者头像 李华
网站建设 2026/6/20 1:34:18

港城大突破性电子皮肤:机器人从此拥有“痛觉反射弧“

📌 目录🚨 机器人终于“懂疼”了!港城大7毫秒神经形态电子皮肤,复刻人类脊髓反射,改写人机交互安全范式一、传统机器人的“致命短板”:触觉响应的“层层审批”困局二、NRE-skin的革命性突破:复刻…

作者头像 李华
网站建设 2026/6/18 17:02:37

OCR性能 benchmark 对比:HunyuanOCR vs PaddleOCR vs EasyOCR

OCR性能 benchmark 对比:HunyuanOCR vs PaddleOCR vs EasyOCR 在文档自动化、智能办公和跨境业务快速发展的今天,一张图片上传后能否“秒级”提取出结构化信息甚至直接翻译成目标语言,已经成为衡量OCR系统先进性的关键标准。传统OCR工具虽然…

作者头像 李华
网站建设 2026/6/14 12:39:20

智能家居控制新方式:HunyuanOCR识别家电说明书实现语音操控

智能家居控制新方式:HunyuanOCR识别家电说明书实现语音操控 在智能音箱早已能“开关灯、调温度”的今天,我们却依然会为一个问题头疼:刚买的进口洗衣机说明书厚厚一本,怎么设置“夜间静音模式”? 传统智能家居助手对此…

作者头像 李华
网站建设 2026/6/15 22:18:25

大学生论文写作助手:HunyuanOCR扫描参考文献并生成引用条目

大学生论文写作助手:HunyuanOCR扫描参考文献并生成引用条目 在高校图书馆的角落里,总能看到这样的场景:一名研究生正对着一堆外文纸质文献拍照,然后逐字输入作者、标题和出版信息到文献管理软件中。稍有疏忽,就可能漏掉…

作者头像 李华
网站建设 2026/6/13 22:15:38

弹幕文字实时识别:HunyuanOCR提取直播视频中的观众评论

弹幕文字实时识别:HunyuanOCR提取直播视频中的观众评论 在一场热门电竞赛事的直播间里,每秒涌出上百条滚动弹幕——“这波操作太秀了!”、“666”、“can we get a subtitle?”。这些密集叠加、中英混杂、字体各异的文字不仅构成了独特的社…

作者头像 李华