当前位置: 首页 > news >正文

网页前端如何通过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

效果预览

文件上传

文件刷新续传

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

文件夹上传

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

下载示例

点击下载完整示例

http://www.jsqmd.com/news/88376/

相关文章:

  • Ursa.Avalonia样式系统终极指南:5大技巧助你构建企业级UI
  • Asio应用(高级):构建高性能、安全、跨平台的网络系统
  • 实习面试题-Spark SQL 面试题
  • CF958A1 Death Stars (easy) 解题报告
  • PS 例程大全
  • wangEditor导入excel数据到html富文本编辑
  • 如何利用JSP实现信创环境的大文件上传?
  • 实习面试题-Kotlin 面试题
  • CF1619G Unusual Minesweeper 解题报告
  • 毕设 stm32 RFID员工打卡门禁系统(源码+硬件+论文)
  • 基于vue的个人博客论坛交流网站_sdj10346_springboot php python nodejs
  • 光伏电池simulink仿真模型 光伏电池建模仿真 包括改变温度 改变辐照度的特性分析 模型可...
  • JSP中如何利用分块技术实现百万文件上传优化?
  • 多交换机VLAN的划分,配置trunk中继链路,链路聚合配置, 利用路由器连接网络,配置静态路由
  • JSP中如何集成SM4加密实现大文件上传存储安全?
  • 如何使用yolov11训练使用—番茄炭疽病与品质检测数据集 炭疽病症状识别、病害区域检测、成熟果实与腐烂果实区分 目标检测 4类 可直接用于模型训练 YOLO适用的txt格式
  • 四旋翼无人机PID控制仿真模型探索
  • wangEditor粘贴ppt母版样式自动适配网页
  • Vim 分屏操作详解
  • 63、技术综合指南:系统配置、数据库管理与网络应用
  • JAVA中如何利用JSP实现视频文件的分片上传?
  • MATLAB/Simulink仿真下的蓄电池储能及双向斩波充放电控制策略
  • 列出自己网站音频书籍资源方法附php代码
  • 48、PHP与C/C++编程实用指南
  • 隐式转换,强制转换,字符串,字符的加操作
  • .NET进阶——深入理解Lambda表达式(2)手搓LINQ语句
  • Android中Compose系列之按钮Button
  • SPSS——判别分析——“一般判别分析”
  • 49、Ubuntu 编程工具与 Mono 开发全解析
  • wangEditor支持pdf书签目录结构导入功能