升级 Spring Boot 3 配置讲解 —— 支持断点传输的文件上传和下载功能

学会这款 🔥全新设计的 Java 脚手架 ,从此面试不再怕!

在这里插入图片描述
在这里插入图片描述

在现代 Web 应用中,文件上传和下载是非常常见的需求。然而,当文件较大时,传统的上传下载方式可能会遇到网络不稳定或传输中断的问题。为了解决这些问题,断点传输(Resumable Upload/Download)成为了一个重要的技术手段。Spring Boot 3 提供了更强大的支持,使得实现断点传输变得更加简单。

本文将详细介绍如何在 Spring Boot 3 中实现支持断点传输的文件上传和下载功能,并通过代码示例帮助你快速上手。


1. 什么是断点传输?

断点传输是指在文件传输过程中,如果传输中断(如网络故障或用户手动暂停),可以从断点处继续传输,而不需要重新开始。这种技术对于大文件传输尤为重要,因为它可以显著减少重复传输的时间和带宽消耗。

  • 断点上传:客户端可以将文件分成多个块(Chunk),分批次上传,服务器端根据上传的块信息进行合并。
  • 断点下载:客户端可以请求文件的某一部分,服务器端根据请求的范围返回对应的文件内容。

2. 环境准备

在开始之前,确保你已经具备以下环境:

  • JDK 17 或更高版本(Spring Boot 3 要求的最低 JDK 版本)
  • Maven 或 Gradle 构建工具
  • Spring Boot 3.x

pom.xml 中添加以下依赖:

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency>
</dependencies>

3. 实现断点上传

3.1 配置文件上传限制

application.properties 中配置文件上传的限制:

# 设置单个文件的最大大小
spring.servlet.multipart.max-file-size=1GB# 设置总上传文件的最大大小
spring.servlet.multipart.max-request-size=1GB

3.2 实现断点上传接口

为了实现断点上传,我们需要记录每个文件的上传进度。以下是一个简单的实现:

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;@Controller
public class ResumableUploadController {// 保存文件块的临时目录private static final String UPLOAD_DIR = "uploads/";// 用于记录文件上传进度的缓存private final Map<String, Long> uploadProgressMap = new HashMap<>();@PostMapping("/upload")@ResponseBodypublic String handleChunkUpload(@RequestParam("file") MultipartFile file,@RequestParam("chunkNumber") int chunkNumber,@RequestParam("totalChunks") int totalChunks,@RequestParam("identifier") String identifier) throws IOException {// 获取文件块的大小long chunkSize = file.getSize();String fileName = file.getOriginalFilename();// 创建临时文件目录File uploadDir = new File(UPLOAD_DIR);if (!uploadDir.exists()) {uploadDir.mkdirs();}// 将文件块写入临时文件String tempFileName = UPLOAD_DIR + identifier + "_" + fileName;try (RandomAccessFile randomAccessFile = new RandomAccessFile(tempFileName, "rw")) {randomAccessFile.seek((chunkNumber - 1) * chunkSize);randomAccessFile.write(file.getBytes());}// 更新上传进度uploadProgressMap.put(identifier, (long) chunkNumber);// 如果所有块都已上传,合并文件if (chunkNumber == totalChunks) {mergeFileChunks(tempFileName, fileName);uploadProgressMap.remove(identifier);return "Upload complete!";}return "Chunk " + chunkNumber + " uploaded!";}private void mergeFileChunks(String tempFileName, String fileName) throws IOException {File mergedFile = new File(UPLOAD_DIR + fileName);try (RandomAccessFile randomAccessFile = new RandomAccessFile(mergedFile, "rw")) {for (int i = 1; i <= uploadProgressMap.size(); i++) {File chunkFile = new File(tempFileName + "_" + i);byte[] chunkData = Files.readAllBytes(chunkFile.toPath());randomAccessFile.write(chunkData);chunkFile.delete(); // 删除临时文件块}}}
}

3.3 前端实现断点上传

在前端,可以使用 JavaScript 将文件分块并发送到服务器。以下是一个简单的示例:

<input type="file" id="fileInput" />
<button onclick="uploadFile()">上传</button><script>async function uploadFile() {const file = document.getElementById('fileInput').files[0];const chunkSize = 1024 * 1024; // 1MBconst totalChunks = Math.ceil(file.size / chunkSize);const identifier = UUID.randomUUID();for (let i = 1; i <= totalChunks; i++) {const chunk = file.slice((i - 1) * chunkSize, i * chunkSize);const formData = new FormData();formData.append('file', chunk);formData.append('chunkNumber', i);formData.append('totalChunks', totalChunks);formData.append('identifier', identifier);await fetch('/upload', {method: 'POST',body: formData});}alert('文件上传完成!');}
</script>

4. 实现断点下载

4.1 实现断点下载接口

Spring Boot 3 支持通过 Range 请求头实现断点下载。以下是一个简单的实现:

import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRange;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;@RestController
public class ResumableDownloadController {private static final String DOWNLOAD_DIR = "uploads/";@GetMapping("/download/{filename:.+}")public ResponseEntity<Resource> downloadFile(@PathVariable String filename,@RequestHeader(value = "Range", required = false) String rangeHeader) throws IOException {Path path = Paths.get(DOWNLOAD_DIR + filename);Resource resource = new UrlResource(path.toUri());if (!resource.exists() || !resource.isReadable()) {return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);}long fileLength = resource.contentLength();if (rangeHeader == null) {// 如果没有 Range 请求头,返回整个文件return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"").header(HttpHeaders.CONTENT_LENGTH, String.valueOf(fileLength)).body(resource);} else {// 解析 Range 请求头List<HttpRange> ranges = HttpRange.parseRanges(rangeHeader);HttpRange range = ranges.get(0);long start = range.getRangeStart(fileLength);long end = range.getRangeEnd(fileLength);// 返回部分文件内容long rangeLength = end - start + 1;return ResponseEntity.status(HttpStatus.PARTIAL_CONTENT).header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"").header(HttpHeaders.CONTENT_RANGE, "bytes " + start + "-" + end + "/" + fileLength).header(HttpHeaders.CONTENT_LENGTH, String.valueOf(rangeLength)).body(resource);}}
}

4.2 测试断点下载

使用支持断点下载的工具(如 curl 或浏览器)测试下载功能。例如:

curl -H "Range: bytes=0-1023" http://localhost:8080/download/example.txt -o example.txt

5. 总结

通过本文的介绍,你已经学会了如何在 Spring Boot 3 中实现支持断点传输的文件上传和下载功能。断点传输技术可以显著提升大文件传输的效率和可靠性,是现代 Web 应用中不可或缺的一部分。

希望本文的内容能够帮助你在实际项目中更好地处理文件上传和下载的需求。如果你有任何问题或建议,欢迎在评论区留言讨论。Happy coding!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/65126.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

框架Tensorflow2

深度学习框架之Tensorflow2 Tensorflow2版本的介绍 Tensorflow(简称tf)是深度学习框架&#xff0c;大大简化了建模的方法和步骤&#xff0c;把Keras Api当作核心&#xff0c;使用非常简单&#xff0c;跨平台&#xff0c;集成各种现成模型&#xff0c;eager mode使得调试起来不…

SpringBoot3-深入理解自动配置类的原理(尚硅谷SpringBoot3-雷神)

文章目录 目录了解自动配置 一、导入对应场景的Mean依赖&#xff1a;1、引入依赖**找到自动配置类的所有配置都存放在哪里** 二、编写主程序&#xff1a;SpringBootApplication观察源码时所需要知道的几个核心注解&#xff1a;1、观察SpringBootApplication源码都做了什么 三、…

Mongo高可用架构解决方案

Mongo主从复制哪些事(仅适用特定场景) 对数据强一致性要求不高的场景,一般微服务架构中不推荐 master节点可读可写操作,当数据有修改时,会将Oplog(操作日志)同步到所有的slave节点上。那么对于从节点来说仅只读,所有slave节点从master节点同步数据,然而从节点之间互相…

商业领域 - 竞标极简理解

竞标极简理解 竞标是一种投标过程&#xff0c;指参与者&#xff08;通常是企业或个人&#xff09;为了获得某个项目或合同的执行权&#xff0c;向招标人&#xff08;通常是采购方或项目发起方&#xff09;提交报价和方案&#xff0c;并争取获得招标人的认可 竞标是一种常见的招…

C#Halcon跨窗口颜色识别

机器视觉是一门让计算机模拟人类视觉功能的学科。颜色识别在其中扮演着重要的角色&#xff0c;它旨在通过对图像中的颜色信息进行分析&#xff0c;从而识别出图像中的目标物体或者区域。例如&#xff0c;在水果分拣系统中&#xff0c;可以根据水果的颜色&#xff08;如苹果的红…

01:C语言的本质

C语言的本质 1、ARM架构与汇编2、局部变量初始化与空间分配2.1、局部变量的初始化2.1、局部变量数组初始化 3、全局变量/静态变量初始化化与空间分配4、堆空间 1、ARM架构与汇编 ARM简要架构如下&#xff1a;CPU&#xff0c;ARM(能读能写)&#xff0c;Flash&#xff08;能读&a…

Transformer知识梳理

Transformer知识梳理 文章目录 Transformer知识梳理什么是Transformer&#xff1f;语言模型迁移学习 Transformer结构注意力层原始结构 总结 什么是Transformer&#xff1f; 语言模型 Transformer模型本质上都是预训练语言模型&#xff0c;大部分采用自监督学习&#xff08;S…

第29天:PHP应用弱类型脆弱Hash加密Bool类型Array数组函数转换比较

#知识点&#xff1a; 1、安全开发-原生PHP-弱类型脆弱 2、安全开发-原生PHP-函数&数据类型 3、安全开发-原生PHP-代码审计案例 1、 和 两个等号是弱比较&#xff0c;使用进行对比的时候&#xff0c;php解析器就会做隐式类型转换&#xff0c;如果两个值的类型不相等就会把两…

STM32F1学习——编码器接口

一、编码器接口 编码器接口可以接收正交编码器的信号&#xff0c;根据编码器旋转产生的正交信号脉冲&#xff0c;通过硬件自动控制CNT值的自增或自减&#xff0c;从而指出编码器的位置、旋转方向和旋转速度。 每个高级定时器和通用定时器都有一个编码器接口&#xff0c;他们会占…

如何删除 Docker 中的悬虚镜像?

在 Docker 中&#xff0c;悬虚镜像&#xff08;Dangling Images&#xff09;是指那些没有 标签 且没有被任何容器使用的镜像。这些镜像通常是由于构建过程中生成的中间层镜像或未正确清理的镜像残留。删除悬虚镜像可以释放磁盘空间并保持 Docker 环境的整洁。 1. 列出悬虚镜像…

网络安全的学习与实践经验(附资料合集)

学习资源 在线学习平台&#xff1a; Hack This Site&#xff1a;提供从初学者到高级难度的挑战任务&#xff0c;适合练习各种网络安全技术。XCTF_OJ&#xff1a;由XCTF组委会开发的免费在线网络安全网站&#xff0c;提供丰富的培训材料和资源。SecurityTube&#xff1a;提供丰…

ts是什么、tsc是什么、tsx是什么、jsx是什么、scss是什么

一、TS (TypeScript): TypeScript 是一种由微软开发的开源编程语言&#xff0c;它是 JavaScript 的一个超集&#xff0c;增加了类型系统和对ES6及以后版本新特性的支持。TypeScript 旨在解决 JavaScript 开发中的可维护性、可扩展性和大型项目中的复杂性问题。它允许开发者在编…

行业商机信息付费小程序系统开发方案

行业商机信息付费小程序系统&#xff0c;主要是整合优质行业资源&#xff0c;实时更新的商机信息。在当今信息爆炸的时代&#xff0c;精准、高效地获取行业商机信息对于企业和个人创业者而言至关重要。 一、使用场景 日常浏览&#xff1a;用户在工作间隙或闲暇时间&#xff0c…

[Qt] 输入控件 | Line | Text | Combo | Spin | Date | Dial | Slider

目录 输入类控件 1、Line Edit 录入个人信息 使用正则表达式验证输入框的数据 验证两次输入的密码一致 切换显示密码 2、Text Edit 获取多行输入框的内容 验证输入框的各种信号 3、Combo Box 使用下拉框模拟麦当劳点餐 从文件中加载下拉框的选项 4、Spin Box 调整…

Flink CDC 自定义函数处理 SQLServer XML类型数据 映射 doris json字段方案

Flink CDC 自定义函数处理 SQLServer XML类型数据方案 1. 背景 因业务使用SQLServer数据库&#xff0c;CDC同步到doris 数仓。对于SQLServer xml类型&#xff0c;doris没有相应的字段对应&#xff0c; 可以使用json来存储xml数据。需要进行一步转换。从 flink 自定义函数入手…

C语言:cJSON将struct结构体与JSON互相转换

文章目录 struct 转 jsonjson 转 struct 文档&#xff1a; https://github.com/DaveGamble/cJSON 项目结构 . ├── libs │ ├── cJSON.c │ └── cJSON.h └── main.c示例 struct 转 json #include "libs/cJSON.h" #include <stdio.h>// defi…

JeeSite 快速开发平台:全能企业级快速开发解决方案|GitCode 光引计划征文展示

投稿人GitCode ID&#xff1a;thinkgem 光引计划投稿项目介绍 JeeSite 快速开发平台&#xff0c;不仅仅是一个后台开发框架&#xff0c;它是一个企业级快速开发解决方案&#xff0c;后端基于经典组合 Spring Boot、Shiro、MyBatis&#xff0c;前端采用 Beetl、Bootstrap、Admi…

2025/1/4期末复习 密码学 按老师指点大纲复习

我们都要坚信&#xff0c;道路越是曲折&#xff0c;前途越是光明。 --------------------------------------------------------------------------------------------------------------------------------- 现代密码学 第五版 杨波 第一章 引言 1.1三大主动攻击 1.中断…

【架构设计(一)】常见的Java架构模式

常见的 Java 架构模式解析 在 Java 开发领域&#xff0c;选择合适的架构模式对于构建高效、可维护且能满足业务需求的软件系统至关重要。本文将深入探讨几种常见的 Java架构模式&#xff0c;包括单体架构与微服务架构、分层架构与微服务架构的对比&#xff0c;以及事件驱动架构…

opencv与halcon的差距及改进方法

本文是直接问ai获得的结果。 在我理解中&#xff0c;这是开源软件与商业非开源工业软件的普遍差距特点。 商业非开源工业软件的人员、资金、时间投入是巨大的&#xff0c;开发人员也不是普通人普通水平。 一般情况下&#xff0c;试图通过开源软件改吧改吧就实现弯道超车&#x…