news 2026/10/15 15:06:58

芯片制造SpringBoot如何实现大文件上传?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
芯片制造SpringBoot如何实现大文件上传?

开发者日记:2023年11月25日 周六 阴
项目名称:跨平台大文件传输系统(WebUploader+Vue3+SpringBoot+腾讯云COS)


项目背景与核心挑战

作为河南独立开发者,近期承接了一个高复杂度外包项目,客户要求实现20G级文件/文件夹跨浏览器上传下载,技术栈涉及:

  • 前端:Vue3(TypeScript)+ WebUploader(兼容IE8)
  • 后端:SpringBoot 3.0 + Oracle 21c
  • 存储:腾讯云COS(需处理分片上传与合并)
  • 兼容性:从IE8到现代浏览器(Chrome/Firefox/Safari/Edge/Opera)

现存痛点:

  1. 网上开源方案仅支持单文件上传,无完整文件夹层级解析逻辑
  2. IE8的ActiveX控件在Windows 11上频繁崩溃
  3. Oracle数据库与MySQL的序列化差异导致进度存储失败
  4. 20G文件传输时,SpringBoot默认超时时间(1分钟)严重不足

技术方案设计

前端架构(Vue3 + WebUploader)

Chrome/Firefox

IE8

用户选择文件/文件夹

浏览器类型

使用FileSystemDirectoryHandle API

调用ActiveX控件递归读取

生成文件树结构(JSON)

计算文件ETag(替代MD5,兼容IE8)

分片上传(WebUploader)

本地存储进度(IndexedDB+localStorage)

后端架构(SpringBoot + Oracle)

是

否

是

否

接收分片

是否首片

创建Oracle任务记录(序列+BLOB)

更新分片进度(JDBC批处理)

存储分片到临时目录

是否全部分片完成

合并文件并上传COS

返回继续上传指令

关键数据库设计(Oracle)
-- 上传任务表CREATETABLEUPLOAD_TASK(TASK_ID VARCHAR2(36)PRIMARYKEY,FILE_ETAG VARCHAR2(64)NOTNULL,RELATIVE_PATH VARCHAR2(1024),-- 保留文件夹层级(如 /project/src/)TOTAL_CHUNKS NUMBER,UPLOADED_CHUNKS NUMBERDEFAULT0,STATUSVARCHAR2(20)CHECK(STATUSIN('PENDING','UPLOADING','COMPLETED','FAILED')),COS_KEY VARCHAR2(1024),CREATE_TIMETIMESTAMPDEFAULTSYSTIMESTAMP);-- 分片存储表(Oracle BLOB优化)CREATETABLEUPLOAD_CHUNK(CHUNK_ID VARCHAR2(72)PRIMARYKEY,-- TASK_ID+CHUNK_INDEXTASK_ID VARCHAR2(36)REFERENCESUPLOAD_TASK(TASK_ID),CHUNK_INDEX NUMBER,CHUNK_DATABLOB,CONSTRAINTUK_TASK_CHUNKUNIQUE(TASK_ID,CHUNK_INDEX));

核心代码实现

前端:文件夹上传与断点续传(Vue3 + TypeScript)
// src/components/FolderUploader.vueimport{ref,onMounted}from'vue';importWebUploaderfrom'webuploader';import{calculateFileETag}from'@/utils/fileHash';// 自定义ETag计算(兼容IE8)exportdefault{setup(){consttaskList=ref>([]);constuploader=ref(null);// 初始化上传器(兼容IE8)constinitUploader=()=>{constisIE8=document.documentMode===8;uploader.value=WebUploader.create({swf:'/static/Uploader.swf',// IE8回退server:'/api/upload/chunk',chunked:true,chunkSize:isIE8?4*1024*1024:20*1024*1024,// IE8限制4MB分片threads:isIE8?1:5,formData:{taskId:localStorage.getItem('currentTaskId')||''},timeout:0// 禁用超时(由后端控制)});// 恢复未完成任务(从IndexedDB)restoreTasksFromDB();};// 递归解析文件夹(跨浏览器)consthandleFolderSelect=async(e:Event)=>{constinput=e.targetasHTMLInputElement;constfiles=input.files;if(!files?.length)return;constparseFolder=async(entries:FileSystemEntry[],parentPath='')=>{for(letentryofentries){if(entry.isFile){constfile=(entryasFileSystemFileEntry).file!;constrelativePath=parentPath?`${parentPath}/${entry.name}`:entry.name;awaitaddUploadTask(file,relativePath);}elseif(entry.isDirectory){constdirReader=(entryasFileSystemDirectoryEntry).createReader();constnewEntries=awaitnewPromise(resolve=>{dirReader.readEntries(resolve);});awaitparseFolder(newEntries,parentPath?`${parentPath}/${entry.name}`:entry.name);}}};// Chrome/Firefox使用showDirectoryPickerif(files[0].webkitGetAsEntry){constentry=files[0].webkitGetAsEntry();if(entry?.isDirectory){constdirReader=entry.createReader();constentries=awaitnewPromise(resolve=>{dirReader.readEntries(resolve);});awaitparseFolder(entries);}else{awaitaddUploadTask(files[0],files[0].name);}}// IE8使用ActiveX(需用户授权)elseif(window.ActiveXObject){// ActiveX实现代码省略(需处理权限弹窗)}};// 添加上传任务constaddUploadTask=async(file:File,relativePath:string)=>{constetag=awaitcalculateFileETag(file);// 使用CRC32+文件大小替代MD5consttask={file,relativePath,etag,chunkCount:Math.ceil(file.size/uploader.value!.options.chunkSize),uploadedChunks:0};// 检查本地是否有未完成记录constexistingTask=awaitgetTaskFromDB(etag);if(existingTask){task.uploadedChunks=existingTask.uploadedChunks;}taskList.value.push(task);saveTaskToDB(task);startUpload(task);};onMounted(()=>{initUploader();document.getElementById('folderInput')?.addEventListener('change',handleFolderSelect);});return{taskList,uploader};}};
后端:SpringBoot分片处理与COS上传
// src/main/java/com/example/uploader/controller/UploadController.java@RestController@RequestMapping("/api/upload")publicclassUploadController{@AutowiredprivateUploadTaskRepositorytaskRepository;@AutowiredprivateUploadChunkRepositorychunkRepository;@AutowiredprivateCOSClientcosClient;// 腾讯云COS客户端// 分片上传接口@PostMapping("/chunk")publicResponseEntityhandleChunk(@RequestParam("file")MultipartFilefile,@RequestParam("taskId")StringtaskId,@RequestParam("chunkIndex")intchunkIndex,@RequestParam("totalChunks")inttotalChunks,@RequestParam("etag")Stringetag,@RequestParam("relativePath")StringrelativePath){// 1. 查询或创建任务UploadTasktask=taskRepository.findById(taskId).orElseGet(()->{UploadTasknewTask=newUploadTask();newTask.setTaskId(taskId);newTask.setFileEtag(etag);newTask.setRelativePath(relativePath);newTask.setTotalChunks(totalChunks);newTask.setStatus("UPLOADING");returntaskRepository.save(newTask);});// 2. 保存分片到Oracle BLOBUploadChunkchunk=newUploadChunk();chunk.setChunkId(taskId+"_"+chunkIndex);chunk.setTaskId(taskId);chunk.setChunkIndex(chunkIndex);try{chunk.setChunkData(file.getBytes());chunkRepository.save(chunk);}catch(IOExceptione){returnResponseEntity.status(500).body("分片保存失败");}// 3. 更新任务进度task.setUploadedChunks(chunkIndex+1);taskRepository.save(task);// 4. 检查是否全部上传完成if(task.getUploadedChunks()>=task.getTotalChunks()){// 启动异步合并任务mergeAndUploadToCOS(task);returnResponseEntity.ok("{\"status\":\"COMPLETED\"}");}returnResponseEntity.ok("{\"status\":\"SUCCESS\"}");}// 异步合并并上传COS@AsyncpublicvoidmergeAndUploadToCOS(UploadTasktask){try{// 1. 从Oracle读取所有分片Listchunks=chunkRepository.findByTaskIdOrderByChunkIndex(task.getTaskId());// 2. 合并文件(流式处理避免内存溢出)PathtempFile=Files.createTempFile("upload_",".tmp");try(OutputStreamout=Files.newOutputStream(tempFile)){for(UploadChunkchunk:chunks){out.write(chunk.getChunkData());}}// 3. 上传到腾讯云COSStringcosKey="uploads/"+task.getTaskId()+"/"+task.getRelativePath();cosClient.putObject(newPutObjectRequest("your-bucket",cosKey,tempFile.toFile()));// 4. 更新任务状态task.setStatus("COMPLETED");task.setCosKey(cosKey);taskRepository.save(task);// 5. 清理临时文件和分片Files.deleteIfExists(tempFile);chunkRepository.deleteByTaskId(task.getTaskId());}catch(Exceptione){task.setStatus("FAILED");taskRepository.save(task);}}}

关键问题解决

  1. IE8兼容性:

    • 使用标签替代已废弃的加载Uploader.swf
    • 通过document.execCommand('SaveAs')实现IE8的下载功能
  2. Oracle性能优化:

    • 对UPLOAD_CHUNK表的TASK_ID字段建立索引
    • 使用JDBC批处理更新进度(addBatch()+executeBatch())
  3. 大文件传输超时:

    • 在SpringBoot配置中增加:
      server:tomcat:connection-timeout:0# 禁用连接超时spring:servlet:multipart:max-file-size:20GBmax-request-size:20GB
  4. 文件夹层级保留:

    • 前端传递relativePath参数(如/docs/2023/report.pdf)
    • 后端直接存储该路径,上传COS时保持原样

求助与社区支持

目前遇到以下难题,已在QQ群(374992201)发布详细日志:

  1. IE8的ActiveX控件在Windows 11上频繁弹出权限警告
  2. Oracle BLOB存储20G文件时出现ORA-01653表空间不足错误
  3. SpringBoot异步任务在合并大文件时被K8s容器终止

完整代码仓库:

  • 前端:https://gitee.com/yourname/vue3-folder-uploader
  • 后端:https://gitee.com/yourname/springboot-cos-uploader

明日计划:

  1. 实现WebUploader的IE8进度条显示
  2. 编写Oracle分片表的分区策略(按任务ID哈希分区)
  3. 测试20G文件在低带宽(2Mbps)下的传输稳定性

(日记结束)

附:技术栈对比表

模块原方案当前方案优化点
前端框架jQueryVue3 + TypeScript类型安全+组件化
上传组件WebUploader基础版定制版(支持文件夹+ETag)递归解析文件夹结构
后端语言JSPSpringBoot 3.0响应式编程+Oracle优化
数据库MySQLOracle 21cBLOB存储优化+分区表
对象存储百度OBS腾讯云COS适配不同的分片API规范

如需完整项目或调试协助,请联系QQ群或留言获取测试账号!

SQL示例

创建数据库

配置数据库连接

自动下载maven依赖

启动项目

启动成功

访问及测试

默认页面接口定义

在浏览器中访问

数据表中的数据

效果预览

文件上传

文件刷新续传

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

文件夹上传

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

批量下载

支持文件批量下载

下载续传

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

文件夹下载

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

示例下载

下载完整示例

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

汽车制造SpringCloud如何上传大文件图纸?

内蒙古金融行业银行单位大文件传输解决方案 作为内蒙古金融行业某上市公司项目负责人,针对集团提出的大文件传输系统需求,本人经过详细调研与技术评估,现提供一套完整的解决方案,确保满足客户对超大文件传输、断点续传、数据安全…

作者头像 李华
网站建设 2026/10/12 7:39:58

鸿蒙 HarmonyOS 6 | AI Kit 集成 CANN Kit 异构计算服务

文章目录一、 CANN Kit 的定位与体系架构说明二、 关键概念 异构计算与 AIPP 硬件加速三、 开发环境与 OMG 工具链准备四、 模型转换的实操要点五、 Native 层的集成逻辑与代码实现六、 进阶优化 内存零拷贝技术七、 总结前言本篇技术博客会带你初步认识 HarmonyOS Next 底层的…

作者头像 李华
网站建设 2026/10/15 17:31:50

AI智能分析系统在明厨亮灶的应用方案

目录 引言 一、方案背景与客户需求 方案背景 客户需求 二、AI智能分析系统方案说明 系统架构 前端设备 AI Box边缘计算设备 算法部署与应用 三、实施效果与优势 实施效果 方案优势 四、结论与展望 引言 随着食品安全监管力度的加强与数字化技术的广泛应用,明厨亮…

作者头像 李华
网站建设 2026/10/15 1:15:28

seo快排是什么?有风险吗?深度揭秘行业内幕与避坑指南

最近这几年,做网站运营和老板们最焦虑的莫过于流量获取。尤其是当老板看到竞争对手的新站几个星期就冲到了首页,而自己辛辛苦苦写内容发外链的站还在几页开外徘徊时,心态很容易崩。这时候,市面上铺天盖地的“7天上首页”、“按天扣…

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

【必收藏】大模型入门指南:从零基础到实战,程序员小白都能懂

在AI浪潮席卷全球的当下,大模型早已不是实验室的专属产物,而是渗透到软件开发、数据分析、智能交互等多个领域的核心工具。对于程序员而言,掌握大模型技术能拓宽职业边界、提升开发效率;对于AI小白来说,入门大模型也是…

作者头像 李华