SpringBoot 文件下载

复制代码
springboot 提供文件下载服务
ChatGPT 说:
ChatGPT
在 Spring Boot 中实现文件下载服务非常简单,可以通过以下步骤实现一个文件下载功能:

1. 创建一个 Spring Boot 项目
确保已创建 Spring Boot 项目,并添加必要的依赖,例如 Spring Web。

xml
复制
编辑
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
2. 创建文件下载控制器
java
复制
编辑
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.nio.file.Path;
import java.nio.file.Paths;

@RestController
public class FileDownloadController {

    private final String fileBasePath = "/path/to/your/files"; // 设置文件存储的根路径

    @GetMapping("/download")
    public ResponseEntity<Resource> downloadFile(@RequestParam String filename) {
        try {
            // 构建文件路径
            Path filePath = Paths.get(fileBasePath).resolve(filename).normalize();
            Resource resource = new UrlResource(filePath.toUri());

            if (!resource.exists()) {
                return ResponseEntity.notFound().build();
            }

            // 设置响应头,支持下载
            String contentDisposition = "attachment; filename=\"" + resource.getFilename() + "\"";
            return ResponseEntity.ok()
                    .contentType(MediaType.APPLICATION_OCTET_STREAM)
                    .header(HttpHeaders.CONTENT_DISPOSITION, contentDisposition)
                    .body(resource);
        } catch (Exception e) {
            return ResponseEntity.internalServerError().build();
        }
    }
}
3. 运行服务并测试
启动应用后,通过浏览器或 API 调试工具(如 Postman)访问下载接口:

bash
复制
编辑
http://localhost:8080/download?filename=test.txt
4. 注意事项
路径安全:

对 filename 参数进行校验,防止目录穿越攻击(如 ../../etc/passwd)。
使用 Paths.get(fileBasePath).resolve(filename).normalize() 确保路径被正规化。
文件存储路径:

确保 fileBasePath 是一个安全的目录,应用服务有权限读取。
大文件下载:

对于大文件,可以使用流式下载,避免内存溢出。Spring 的 Resource 自动支持流式响应。
异常处理:

捕获文件不存在、读取错误等异常,并返回友好的错误信息。
以上代码可以作为基础实现。如果需要更复杂的功能(如权限控制、日志记录等),可以在此基础上扩展。







您说:
大文件下载实现
ChatGPT 说:
ChatGPT
在 Spring Boot 中实现大文件的下载,可以通过 流式传输 的方式,这样可以避免将整个文件加载到内存中,降低内存使用压力。以下是实现步骤:

1. 使用 InputStream 流式下载
java
复制
编辑
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.io.InputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

@RestController
public class LargeFileDownloadController {

    private final String fileBasePath = "/path/to/your/files"; // 文件根目录

    @GetMapping("/download/large")
    public ResponseEntity<?> downloadLargeFile(@RequestParam String filename) {
        File file = new File(fileBasePath, filename);

        if (!file.exists()) {
            return ResponseEntity.notFound().build();
        }

        try {
            InputStream fileInputStream = new FileInputStream(file);

            // 设置响应头,支持流式下载
            String contentDisposition = "attachment; filename=\"" + filename + "\"";

            return ResponseEntity.ok()
                    .contentType(MediaType.APPLICATION_OCTET_STREAM)
                    .header(HttpHeaders.CONTENT_DISPOSITION, contentDisposition)
                    .body(new InputStreamResource(fileInputStream));
        } catch (IOException e) {
            return ResponseEntity.internalServerError().body("Error occurred while reading the file.");
        }
    }
}
2. 使用 StreamingResponseBody 提供更高效的流式下载
StreamingResponseBody 是 Spring 提供的一种用于流式响应的接口,可以更高效地处理大文件。

java
复制
编辑
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;

import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;

@RestController
public class LargeFileDownloadController {

    private final String fileBasePath = "/path/to/your/files"; // 文件根目录

    @GetMapping("/download/large/stream")
    public ResponseEntity<StreamingResponseBody> downloadLargeFileStream(@RequestParam String filename) {
        File file = new File(fileBasePath, filename);

        if (!file.exists()) {
            return ResponseEntity.notFound().build();
        }

        StreamingResponseBody responseBody = outputStream -> {
            try (FileInputStream inputStream = new FileInputStream(file)) {
                byte[] buffer = new byte[1024 * 8]; // 8KB 缓冲区
                int bytesRead;
                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, bytesRead);
                    outputStream.flush(); // 确保数据即时写出
                }
            }
        };

        String contentDisposition = "attachment; filename=\"" + filename + "\"";

        return ResponseEntity.ok()
                .contentType(MediaType.APPLICATION_OCTET_STREAM)
                .header(HttpHeaders.CONTENT_DISPOSITION, contentDisposition)
                .body(responseBody);
    }
}
3. 运行和测试
启动服务后,使用以下 URL 测试下载功能:

text
复制
编辑
http://localhost:8080/download/large/stream?filename=bigfile.zip
4. 注意事项
流式传输的优势:

文件内容分块传输,避免一次性加载到内存。
适用于大文件下载,如视频、压缩包等。
性能优化:

调整缓冲区大小(如 byte[] buffer = new byte[1024 * 64])。
根据网络带宽和文件大小选择适当的缓冲区。
错误处理:

捕获 IOException,返回用户友好的错误信息。
多线程支持:

StreamingResponseBody 默认是异步执行的,Spring 会分配线程处理,不会阻塞主线程。
权限验证:

如果涉及敏感文件,确保只有授权用户能访问。
断点续传(可选):

如果需要支持断点续传功能,可实现 Range 请求处理逻辑。
此代码已经足够支持大文件下载需求,性能优异,资源占用低。
复制代码

 

springboot 提供文件下载服务
ChatGPT 说:
ChatGPT

在 Spring Boot 中实现文件下载服务非常简单,可以通过以下步骤实现一个文件下载功能:

1. 创建一个 Spring Boot 项目

确保已创建 Spring Boot 项目,并添加必要的依赖,例如 Spring Web。

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

2. 创建文件下载控制器

java
import org.springframework.core.io.Resource; import org.springframework.core.io.UrlResource; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.nio.file.Path; import java.nio.file.Paths; @RestController public class FileDownloadController { private final String fileBasePath = "/path/to/your/files"; // 设置文件存储的根路径 @GetMapping("/download") public ResponseEntity<Resource> downloadFile(@RequestParam String filename) { try { // 构建文件路径 Path filePath = Paths.get(fileBasePath).resolve(filename).normalize(); Resource resource = new UrlResource(filePath.toUri()); if (!resource.exists()) { return ResponseEntity.notFound().build(); } // 设置响应头,支持下载 String contentDisposition = "attachment; filename=\"" + resource.getFilename() + "\""; return ResponseEntity.ok() .contentType(MediaType.APPLICATION_OCTET_STREAM) .header(HttpHeaders.CONTENT_DISPOSITION, contentDisposition) .body(resource); } catch (Exception e) { return ResponseEntity.internalServerError().build(); } } }

3. 运行服务并测试

启动应用后,通过浏览器或 API 调试工具(如 Postman)访问下载接口:

bash
http://localhost:8080/download?filename=test.txt

4. 注意事项

  1. 路径安全

    • filename 参数进行校验,防止目录穿越攻击(如 ../../etc/passwd)。
    • 使用 Paths.get(fileBasePath).resolve(filename).normalize() 确保路径被正规化。
  2. 文件存储路径

    • 确保 fileBasePath 是一个安全的目录,应用服务有权限读取。
  3. 大文件下载

    • 对于大文件,可以使用流式下载,避免内存溢出。Spring 的 Resource 自动支持流式响应。
  4. 异常处理

    • 捕获文件不存在、读取错误等异常,并返回友好的错误信息。

以上代码可以作为基础实现。如果需要更复杂的功能(如权限控制、日志记录等),可以在此基础上扩展。

 
 
您说:
大文件下载实现
ChatGPT 说:
ChatGPT

在 Spring Boot 中实现大文件的下载,可以通过 流式传输 的方式,这样可以避免将整个文件加载到内存中,降低内存使用压力。以下是实现步骤:


1. 使用 InputStream 流式下载

java
import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.io.InputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; @RestController public class LargeFileDownloadController { private final String fileBasePath = "/path/to/your/files"; // 文件根目录 @GetMapping("/download/large") public ResponseEntity<?> downloadLargeFile(@RequestParam String filename) { File file = new File(fileBasePath, filename); if (!file.exists()) { return ResponseEntity.notFound().build(); } try { InputStream fileInputStream = new FileInputStream(file); // 设置响应头,支持流式下载 String contentDisposition = "attachment; filename=\"" + filename + "\""; return ResponseEntity.ok() .contentType(MediaType.APPLICATION_OCTET_STREAM) .header(HttpHeaders.CONTENT_DISPOSITION, contentDisposition) .body(new InputStreamResource(fileInputStream)); } catch (IOException e) { return ResponseEntity.internalServerError().body("Error occurred while reading the file."); } } }

2. 使用 StreamingResponseBody 提供更高效的流式下载

StreamingResponseBody 是 Spring 提供的一种用于流式响应的接口,可以更高效地处理大文件。

java
import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody; import java.io.File; import java.io.FileInputStream; import java.io.OutputStream; @RestController public class LargeFileDownloadController { private final String fileBasePath = "/path/to/your/files"; // 文件根目录 @GetMapping("/download/large/stream") public ResponseEntity<StreamingResponseBody> downloadLargeFileStream(@RequestParam String filename) { File file = new File(fileBasePath, filename); if (!file.exists()) { return ResponseEntity.notFound().build(); } StreamingResponseBody responseBody = outputStream -> { try (FileInputStream inputStream = new FileInputStream(file)) { byte[] buffer = new byte[1024 * 8]; // 8KB 缓冲区 int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); outputStream.flush(); // 确保数据即时写出 } } }; String contentDisposition = "attachment; filename=\"" + filename + "\""; return ResponseEntity.ok() .contentType(MediaType.APPLICATION_OCTET_STREAM) .header(HttpHeaders.CONTENT_DISPOSITION, contentDisposition) .body(responseBody); } }

3. 运行和测试

启动服务后,使用以下 URL 测试下载功能:

text
http://localhost:8080/download/large/stream?filename=bigfile.zip

4. 注意事项

  1. 流式传输的优势

    • 文件内容分块传输,避免一次性加载到内存。
    • 适用于大文件下载,如视频、压缩包等。
  2. 性能优化

    • 调整缓冲区大小(如 byte[] buffer = new byte[1024 * 64])。
    • 根据网络带宽和文件大小选择适当的缓冲区。
  3. 错误处理

    • 捕获 IOException,返回用户友好的错误信息。
  4. 多线程支持

    • StreamingResponseBody 默认是异步执行的,Spring 会分配线程处理,不会阻塞主线程。
  5. 权限验证

    • 如果涉及敏感文件,确保只有授权用户能访问。
  6. 断点续传(可选)

    • 如果需要支持断点续传功能,可实现 Range 请求处理逻辑。

此代码已经足够支持大文件下载需求,性能优异,资源占用低。

posted @   嘉合  阅读(30)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端
点击右上角即可分享
微信分享提示