news 2026/4/10 23:31:42

国防领域,SpringMVC如何支持百M大文件的稳定上传?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
国防领域,SpringMVC如何支持百M大文件的稳定上传?

项目技术方案:大文件传输系统(企业级高可用方案)
编制:北京某互联网企业 前端研发部 - 张工
日期: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/3/16 5:56:50

嵌入式拉篮品牌哪个好?五款热门产品深度解析与推荐

引言 在厨房装修与改造中,嵌入式拉篮已成为提升收纳效率与空间美感的关键组件。面对市场上众多品牌与型号,消费者常感困惑:嵌入式拉篮品牌哪个好?选择时需综合考虑品牌口碑、产品设计、材质工艺、收纳灵活性及性价比。 本文旨在…

作者头像 李华
网站建设 2026/4/5 10:47:51

用Matlab探索轨道车辆垂向振动:别样视角与Simpack的不同

与simpack不同,matlab建立轨道车辆(垂向)振动输入相应激励分析振动等 垂向 轨道车辆 在轨道车辆动力学研究领域,Simpack和Matlab都是常用工具,但它们有着不同的“性格”。今天咱就来聊聊Matlab在建立轨道车辆垂向振动…

作者头像 李华
网站建设 2026/4/2 7:37:43

如何用显卡性能优化工具实现游戏画质与帧率的双重提升?

如何用显卡性能优化工具实现游戏画质与帧率的双重提升? 【免费下载链接】dlss-swapper 项目地址: https://gitcode.com/GitHub_Trending/dl/dlss-swapper 当你在4K分辨率下激战游戏却遭遇帧率骤降,或升级显卡后仍未体验到应有画质时,…

作者头像 李华
网站建设 2026/4/5 19:11:09

6款搭载AI的论文工具因文本优化与多人协作,入选学术实用工具榜单

针对学术论文写作需求,目前市场上有多种AI工具可同时满足写作辅助与降重需求。这些智能平台通过自然语言处理技术提供论文框架生成、内容优化以及相似度检测功能,适用于毕业论文撰写、课程报告整理等场景。值得注意的是,此类工具应作为效率提…

作者头像 李华
网站建设 2026/4/11 1:36:14

导师严选8个降AI率工具,千笔帮你轻松降AIGC

AI降重工具,为论文护航 在当今学术写作中,AI生成内容的普及让许多学生面临一个共同难题:如何降低AIGC率、去除AI痕迹,同时保持论文的语义通顺和逻辑清晰。对于专科生而言,论文不仅是学业的重要组成部分,更…

作者头像 李华
网站建设 2026/4/11 2:18:10

突破4大限制:6步打造多人分屏游戏系统

突破4大限制:6步打造多人分屏游戏系统 【免费下载链接】nucleuscoop Starts multiple instances of a game for split-screen multiplayer gaming! 项目地址: https://gitcode.com/gh_mirrors/nu/nucleuscoop 在游戏世界中,分屏游戏工具正在重新定…

作者头像 李华