第一章-08-响应类型-JSON格式
2026/5/16 19:31:53
项目技术方案:大文件传输系统(信创兼容版)
编制:湖南长沙某软件公司 技术部
日期:2023年11月20日
公司承接政府项目,需开发一套支持50G文件传输的系统,核心需求如下:
结论:现有开源方案均无法满足信创兼容+源代码授权+高稳定性需求,需自研或采购商业产品源代码。
基于公司研发能力,建议采用以下架构:
// src/components/FileUploader.vue (主组件)import{ref}from'vue';importSM4from'sm4.js';// 国密加密库exportdefault{setup(){constfiles=ref([]);constchunkSize=10*1024*1024;// 10MB分片// 处理文件夹上传(递归生成文件树)consthandleFileChange=(e)=>{constitems=e.target.files;constfileTree=buildFileTree(items);files.value=flattenFileTree(fileTree);};// 构建文件夹层级结构constbuildFileTree=(items)=>{consttree={};Array.from(items).forEach(file=>{constpath=file.webkitRelativePath.split('/');letcurrent=tree;path.forEach((part,i)=>{if(i===path.length-1){current[part]={file,path:file.webkitRelativePath};}else{current[part]=current[part]||{};current=current[part];}});});returntree;};// 上传逻辑(断点续传核心)conststartUpload=async()=>{for(constfileObjoffiles.value){const{file,path}=fileObj;constfileId=awaitinitUpload(file.name,file.size,path);// 检查已上传分片(从LocalStorage或服务端)constuploadedChunks=awaitcheckUploadedChunks(fileId);for(letstart=0;start<file.size;start+=chunkSize){if(uploadedChunks.includes(start/chunkSize))continue;constchunk=file.slice(start,start+chunkSize);constencryptedChunk=SM4.encrypt(chunk,'secret-key');awaituploadChunk(fileId,start,encryptedChunk);// 保存进度到LocalStoragelocalStorage.setItem(`upload_${fileId}_progress`,start);}awaitmergeChunks(fileId);}};return{handleFileChange,startUpload};}};// UploadServlet.java (分片上传接口)@WebServlet("/api/upload")@MultipartConfigpublicclassUploadServletextendsHttpServlet{privatestaticfinalStringTEMP_DIR="/data/upload_temp/";protectedvoiddoPost(HttpServletRequestreq,HttpServletResponseresp){Stringaction=req.getParameter("action");if("init".equals(action)){// 初始化上传任务(生成唯一ID)StringfileId=UUID.randomUUID().toString();StringfileName=req.getParameter("name");longfileSize=Long.parseLong(req.getParameter("size"));StringfilePath=req.getParameter("path");// 保存元数据到数据库(适配多数据库)saveToDatabase(fileId,fileName,fileSize,filePath);resp.getWriter().write(fileId);}elseif("chunk".equals(action)){// 处理分片上传StringfileId=req.getParameter("fileId");longchunkIndex=Long.parseLong(req.getParameter("chunkIndex"));PartfilePart=req.getPart("chunk");// 解密分片(示例:SM4)StringencryptedData=IOUtils.toString(filePart.getInputStream(),StandardCharsets.UTF_8);byte[]decryptedData=SM4Util.decrypt(encryptedData,"secret-key");// 保存分片Files.write(Paths.get(TEMP_DIR+fileId+"_"+chunkIndex),decryptedData);// 记录分片状态(Redis或数据库)markChunkUploaded(fileId,chunkIndex);}}}// 前端断点续传逻辑constcheckUploadedChunks=async(fileId)=>{// 1. 从LocalStorage读取本地进度constlocalProgress=localStorage.getItem(`upload_${fileId}_progress`);if(localProgress){return[parseInt(localProgress)/chunkSize];}// 2. 服务端二次校验(避免多设备冲突)constresponse=awaitfetch(`/api/upload?action=check&fileId=${fileId}`);returnawaitresponse.json();};浏览器兼容:
操作系统适配:
数据库适配:
// 通用JDBC工具类(适配多数据库)publicclassDBUtil{privatestaticDataSourcedataSource;static{StringdbType=System.getProperty("db.type");if("dm".equals(dbType)){// 达梦数据库配置dataSource=newDmDataSource();}elseif("kingbase".equals(dbType)){// 人大金仓配置dataSource=newKingbaseDataSource();}else{// MySQL/Oracle等dataSource=newHikariDataSource();}}}(签名:湖南长沙某软件公司 技术经理 李工)
备注:建议优先采购成熟的商业产品源代码(如支持国密的Plupload),避免自研周期过长。如需进一步讨论,请联系技术部邮箱:tech@company.com。
导入到Eclipse:点击查看教程
导入到IDEA:点击查看教程
springboot统一配置:点击查看教程
NOSQL示例不需要任何配置,可以直接访问测试
选择对应的数据表脚本,这里以SQL为例
up6/upload/年/月/日/guid/filename
支持离线保存文件进度,在关闭浏览器,刷新浏览器后进行不丢失,仍然能够继续上传
支持上传文件夹并保留层级结构,同样支持进度信息离线保存,刷新页面,关闭页面,重启系统不丢失上传进度。
点击下载完整示例