news 2026/5/11 3:36:02

网页前端如何通过JSP实现大文件秒传功能?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
网页前端如何通过JSP实现大文件秒传功能?

大文件上传系统开发指南(基于原生JS+SpringBoot)

项目背景

老哥我最近接了个"硬骨头"项目,客户要求实现20G大文件上传下载,还要支持文件夹结构保留、加密传输、断点续传,还要兼容IE9这种古董浏览器。预算只有100块,还要7×24小时技术支持…这活儿简直比相亲还难!

不过没关系,谁让我进了这个"坑"呢?下面我就把这段时间折腾出来的代码和经验分享给大家,希望能帮到同样在"水深火热"中的同行们。

技术选型

  • 前端:Vue3 CLI + 原生JavaScript(客户要求必须用原生JS实现上传核心功能)
  • 后端:SpringBoot + Tomcat
  • 数据库:MySQL(主要存用户信息和文件元数据)
  • 文件存储:直接服务器存储(简单粗暴,符合预算)
  • 加密:SM4(国密)和AES双支持

系统架构

浏览器(IE9+等) ←HTTP/HTTPS→ SpringBoot后端 ←本地文件IO→ 服务器存储 ↑ MySQL

前端实现(Vue3 + 原生JS上传核心)

1. 文件选择组件(支持文件夹)

export default { data() { return { fileList: [], isUploading: false, progress: 0, chunkSize: 5 * 1024 * 1024, // 5MB每片 currentUploads: {} } }, methods: { triggerFileInput() { document.getElementById('fileInput').click(); }, handleFileChange(e) { const files = Array.from(e.target.files); if (files.length === 0) return; // 处理文件夹结构 const fileTree = {}; files.forEach(file => { const path = file.webkitRelativePath || file.name; this.fileList.push({ file: file, relativePath: path, size: file.size, chunks: Math.ceil(file.size / this.chunkSize), uploadedChunks: 0 }); }); }, } }

后端实现(SpringBoot)

1. 文件上传控制器

// src/main/java/com/example/uploader/controller/FileUploadController.javapackagecom.example.uploader.controller;@RestController@RequestMapping("/api")publicclassFileUploadController{@Value("${file.upload-dir}")privateStringuploadDir;// 存储上传进度信息(实际项目应该用数据库)privatefinalMapprogressMap=newConcurrentHashMap<>();@PostMapping("/upload")publicMaphandleFileUpload(@RequestParam("file")MultipartFilefile,@RequestParam("relativePath")StringrelativePath,@RequestParam("totalChunks")inttotalChunks,@RequestParam("currentChunk")intcurrentChunk,@RequestParam("fileSize")longfileSize,@RequestParam("fileMd5")StringfileMd5,HttpServletRequestrequest)throwsIOException{Mapresult=newHashMap<>();try{// 创建文件存储目录(保留文件夹结构)PathfilePath=Paths.get(uploadDir,relativePath);Files.createDirectories(filePath.getParent());// 如果是加密上传,这里应该先解密(示例省略)// 以追加模式写入文件块try(RandomAccessFilerandomAccessFile=newRandomAccessFile(filePath.toFile(),"rw")){randomAccessFile.seek((long)currentChunk*5*1024*1024);// 5MB每块randomAccessFile.write(file.getBytes());}// 更新上传进度UploadProgressprogress=progressMap.computeIfAbsent(fileMd5,k->newUploadProgress(fileMd5,relativePath,fileSize,totalChunks));progress.markChunkUploaded(currentChunk);// 如果是最后一块,清理进度信息if(progress.isComplete()){progressMap.remove(fileMd5);// 这里可以触发文件后处理,如加密存储等}result.put("success",true);result.put("message","Chunk uploaded successfully");result.put("uploadedChunks",progress.getUploadedChunks());}catch(Exceptione){result.put("success",false);result.put("message","Upload failed: "+e.getMessage());}returnresult;}}

2. 文件下载控制器

// src/main/java/com/example/uploader/controller/FileDownloadController.java@RestController@RequestMapping("/api")publicclassFileDownloadController{@Value("${file.upload-dir}")privateStringuploadDir;@GetMapping("/download")publicResponseEntitydownloadFile(@RequestParamStringrelativePath,HttpServletRequestrequest)throwsIOException{PathfilePath=Paths.get(uploadDir,relativePath).normalize();Resourceresource=newUrlResource(filePath.toUri());if(!resource.exists()){returnResponseEntity.notFound().build();}// 确定内容类型StringcontentType=request.getServletContext().getMimeType(resource.getFile().getAbsolutePath());if(contentType==null){contentType="application/octet-stream";}returnResponseEntity.ok().contentType(MediaType.parseMediaType(contentType)).header(HttpHeaders.CONTENT_DISPOSITION,"attachment; filename=\""+filePath.getFileName()+"\"").body(resource);}}

3. 加密工具类(简化版)

// src/main/java/com/example/uploader/util/CryptoUtil.javapackagecom.example.uploader.util;importjavax.crypto.Cipher;importjavax.crypto.spec.SecretKeySpec;importjava.util.Base64;publicclassCryptoUtil{privatestaticfinalStringAES="AES";// 实际项目应该从安全配置中获取密钥privatestaticfinalbyte[]AES_KEY="ThisIsASecretKey1234567890".getBytes();// 16/24/32字节publicstaticbyte[]encryptAES(byte[]data)throwsException{SecretKeySpeckeySpec=newSecretKeySpec(AES_KEY,AES);Ciphercipher=Cipher.getInstance(AES);cipher.init(Cipher.ENCRYPT_MODE,keySpec);returncipher.doFinal(data);}}

配置文件

application.properties

# 文件上传目录(确保应用有写入权限) file.upload-dir=./uploads # Spring Boot默认配置 server.port=8080 spring.servlet.multipart.max-file-size=10GB spring.servlet.multipart.max-request-size=10GB # 数据库配置(如果需要) spring.datasource.url=jdbc:mysql://localhost:3306/uploader?useSSL=false&serverTimezone=UTC spring.datasource.username=root spring.datasource.password=password spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

部署说明

  1. 环境准备

    • JDK 8+
    • Maven
    • Node.js (用于前端开发)
    • MySQL (可选,如果需要数据库)
  2. 构建前端

    cdfrontendnpminstallnpmrun build
  3. 构建后端

    mvn clean package
  4. 部署

    • 将前端构建产物(dist目录)复制到SpringBoot的src/main/resources/static目录
    • 运行SpringBoot应用:
      java -jar target/uploader-0.0.1-SNAPSHOT.jar
  5. Nginx配置(可选)
    如果需要处理大文件上传,建议使用Nginx反向代理:

    server { listen 80; server_name yourdomain.com; client_max_body_size 21G; location / { proxy_pass http://localhost:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }

兼容性处理

IE9兼容性方案

由于IE9不支持FormDataFile API的某些特性,我们需要做特殊处理:

  1. 前端修改
// 在FileUploader.vue中添加IE9兼容代码methods:{handleFileChange(e){constfiles=e.target.files;if(!files){// IE9兼容处理this.handleIE9FileSelect();return;}// 原有代码...},}
  1. 后端调整

对于IE9的上传请求,可能需要使用传统的multipart/form-data方式而非分块上传。

加密传输实现

如果需要端到端加密,可以在前端加密后上传:

// 在uploadFile方法中添加加密处理asyncuploadFile(fileItem){// ...之前的代码constchunk=file.slice(start,end);letencryptedChunk=chunk;// 根据配置选择加密方式if(this.encryptType==='AES'){encryptedChunk=awaitthis.encryptAES(chunk);}elseif(this.encryptType==='SM4'){encryptedChunk=awaitthis.encryptSM4(chunk);}constformData=newFormData();formData.append('file',newBlob([encryptedChunk]));// ...其他参数// ...上传代码},

性能优化建议

  1. 分块大小调整:根据网络情况动态调整分块大小(5MB-20MB之间)
  2. 并发控制:根据用户带宽和设备性能调整并发上传数
  3. Web Worker:将哈希计算和加密操作放到Web Worker中,避免阻塞UI
  4. 本地缓存:使用IndexedDB缓存已计算的哈希值
  5. 心跳机制:定期向服务器发送心跳,维护上传会话

完整项目结构

file-uploader/ ├── frontend/ # Vue3前端 │ ├── src/ │ │ ├── components/ │ │ │ └── FileUploader.vue │ │ ├── App.vue │ │ └── main.js │ ├── package.json │ └── vue.config.js ├── backend/ # SpringBoot后端 │ ├── src/ │ │ ├── main/ │ │ │ ├── java/com/example/uploader/ │ │ │ │ ├── controller/ │ │ │ │ ├── util/ │ │ │ │ └── Application.java │ │ │ └── resources/ │ │ │ └── application.properties │ └── pom.xml ├── uploads/ # 文件存储目录(自动创建) ├── nginx.conf # Nginx配置示例 └── README.md # 项目说明

总结

这个项目确实是个挑战,特别是在100元预算和兼容IE9的双重限制下。不过通过分块上传、断点续传和合理的架构设计,我们还是能够实现客户的需求。

关键点总结:

  1. 前端使用原生JS实现核心上传逻辑,Vue3负责UI和状态管理
  2. 后端SpringBoot处理文件存储和进度跟踪
  3. 分块上传+本地缓存实现断点续传
  4. 保留完整的文件夹结构
  5. 通过Nginx处理大文件上传

实际项目中,你可能还需要:

  • 添加用户认证
  • 实现更完善的错误处理和重试机制
  • 添加文件预览功能
  • 实现更安全的加密方案
  • 添加管理员界面

希望这个示例能帮到你,也欢迎加入我们的QQ群(374992201)一起交流技术、合作项目。群里定期有技术分享和红包活动,还有项目合作机会哦!

最后提醒一句:这种预算的项目,记得在合同里明确需求范围和变更条款,不然很容易亏本哦!

导入项目

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

工程

NOSQL

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

创建数据表

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

修改数据库连接信息

访问页面进行测试

文件存储路径

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

效果预览

文件上传

文件刷新续传

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

文件夹上传

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

下载示例

点击下载完整示例

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

59、Ubuntu系统全解析:版本、应用与安装指南

Ubuntu系统全解析:版本、应用与安装指南 1. Ubuntu版本介绍 自2004年10月首次发布以来,Ubuntu为其版本选择了独特的命名方式。它摒弃了常见的版本编号,而是采用发布的月份和年份并颠倒顺序来命名。例如,2004年10月的首次发布版本为4.10,随后迅速推出了5.04(2005年4月)…

作者头像 李华
网站建设 2026/5/10 22:14:10

34、Bash脚本中的循环控制与故障排查

Bash脚本中的循环控制与故障排查 1. 循环控制 在Bash脚本中,循环是一种强大的工具,可用于重复执行特定的代码块。下面将介绍 while 、 until 循环以及如何在循环中控制程序流程。 1.1 while 循环 while 循环会在条件为真时持续执行代码块。以下是一个简单菜单程序…

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

直接撸起袖子开干!今天咱们聊聊怎么用LabVIEW整一个带报警记录的上位机监控系统。这玩意儿在工业现场特别实用,尤其是需要24小时盯着设备状态的时候

labview上位机监测报警记录&#xff0c;状态显示。 报警记录存储&#xff0c;存储格式txt。 csv保存文件。先看状态显示部分。LabVIEW的前面板放几个指示灯控件就能实时反映设备状态&#xff0c;比如用绿色圆形表示正常&#xff0c;红色三角表示报警。背后用个While循环不断读取…

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

基于A*算法的无人机三维动态避障路径规划设计,MATLAB编程实现

基于A* 算法的无人机三维路径规划算法&#xff0c;可以动态避障&#xff0c;自己可以规定设计障碍物位置&#xff0c;MATLAB编程实现。 无人机在三维空间耍杂技这事儿&#xff0c;靠的就是路径规划的真功夫。今天咱们来聊个硬核玩法——基于MATLAB实现的A*算法三维动态避障系统…

作者头像 李华
网站建设 2026/5/8 13:15:56

基于vue的宠物寄养机构管理系统_96zn64i1_springboot php python nodejs

目录具体实现截图项目介绍论文大纲核心代码部分展示项目运行指导结论源码获取详细视频演示 &#xff1a;文章底部获取博主联系方式&#xff01;同行可合作具体实现截图 本系统&#xff08;程序源码数据库调试部署讲解&#xff09;同时还支持java、ThinkPHP、Node.js、Spring B…

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

20、GTK+ Tree View 开发指南

GTK+ Tree View 开发指南 1. 引言 在 GTK+ 开发中,Tree View 是一个非常重要的组件,它实现了 MVC(Model-View-Controller)模式中的视图部分。用户可以通过 Tree View 与数据进行交互,如选择行、展开或折叠树等。本文将详细介绍 GTK+ 中 Tree View 的相关函数、属性、信号…

作者头像 李华