• Spring Boot实现对超大文件进行异步压缩下载


     在Web应用中,文件下载功能是一个常见的需求,特别是当你需要提供用户下载各种类型的文件时。本文将演示如何使用Spring Boot框架来实现一个简单而强大的文件下载功能。我们将创建一个RESTful API,通过该API,用户可以下载问价为ZIP压缩文件。

    1. 创建Spring Boot 项目

    首先,确保你已经创建了一个Spring Boot项目,并在项目中添加了所需的依赖。在这个示例中,我们将使用Spring Boot的Web模块和Spring的MVC框架

    2. 编写下载控制器

    创建一个名为DownloadController的RESTful控制器,用于处理文件下载请求。在这个控制器中,我们将定义一个downloadStudentWork方法,用于下载学生作品的ZIP压缩文件。具体文件流来源与具体业务。

    1. @RestController
    2. @RequestMapping("/download")
    3. public class DownloadController {
    4. @GetMapping("/studentWork")
    5. public ResponseEntity downloadStudentWork() {
    6. HttpHeaders headers = new HttpHeaders();
    7. headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
    8. String encodedFileName = "作品名称-学生姓名.zip";
    9. try {
    10. encodedFileName = URLEncoder.encode(encodedFileName, StandardCharsets.UTF_8.toString());
    11. } catch (UnsupportedEncodingException e) {
    12. e.printStackTrace();
    13. }
    14. headers.setContentDispositionFormData("attachment", encodedFileName);
    15. StreamingResponseBody responseBody = outputStream -> {
    16. try (ZipOutputStream zipOut = new ZipOutputStream(outputStream)) {
    17. // 假设这是学生的作品内容视频文件流
    18. InputStream videoStream = getStudentVideoStream();
    19. addToZip(zipOut, videoStream, "作品视频.mkv");
    20. // 添加更多附件,如果有的话
    21. zipOut.finish();
    22. } catch (IOException e) {
    23. // 处理异常
    24. }
    25. };
    26. return new ResponseEntity<>(responseBody, headers, HttpStatus.OK);
    27. }
    28. private void addToZip(ZipOutputStream zipOut, InputStream inputStream, String fileName) throws IOException {
    29. ZipEntry zipEntry = new ZipEntry(fileName);
    30. zipOut.putNextEntry(zipEntry);
    31. byte[] buffer = new byte[1024];
    32. int bytesRead;
    33. while ((bytesRead = inputStream.read(buffer)) != -1) {
    34. zipOut.write(buffer, 0, bytesRead);
    35. }
    36. zipOut.closeEntry();
    37. inputStream.close();
    38. }
    39. // 获取文件流
    40. private InputStream getStudentVideoStream() throws FileNotFoundException {
    41. // 附件信息
    42. FileInputStream inputStream = new FileInputStream("C:\\Users\\28111\\Videos\\2023-09-14 21-30-36.mkv");
    43. return inputStream;
    44. }
    45. }

    当然,也可以用这种方式进行下载,也就是我们常用的void返回值这种方式

    1. package com.ly.cloud.controller.artworkEntries;
    2. import org.springframework.web.bind.annotation.GetMapping;
    3. import org.springframework.web.bind.annotation.RequestMapping;
    4. import org.springframework.web.bind.annotation.RestController;
    5. import javax.servlet.http.HttpServletResponse;
    6. import java.io.*;
    7. import java.net.URLEncoder;
    8. import java.nio.charset.StandardCharsets;
    9. import java.util.zip.ZipEntry;
    10. import java.util.zip.ZipOutputStream;
    11. @RestController
    12. @RequestMapping("/download")
    13. public class DownloadController {
    14. @GetMapping("/studentWork")
    15. public void downloadStudentWork(HttpServletResponse response) {
    16. // 设置响应头信息
    17. response.setContentType("application/zip");
    18. String encodedFileName = "作品名称-学生姓名.zip";
    19. try {
    20. encodedFileName = URLEncoder.encode(encodedFileName, StandardCharsets.UTF_8.toString());
    21. } catch (UnsupportedEncodingException e) {
    22. e.printStackTrace();
    23. }
    24. response.setHeader("Content-Disposition", "attachment; filename=" + encodedFileName);
    25. try (OutputStream outputStream = response.getOutputStream(); ZipOutputStream zipOut = new ZipOutputStream(outputStream)) {
    26. // 假设这是学生的作品内容视频文件流
    27. InputStream videoStream = getStudentVideoStream();
    28. addToZip(zipOut, videoStream, "作品视频.mkv");
    29. // 添加更多附件,如果有的话
    30. zipOut.finish();
    31. } catch (IOException e) {
    32. // 处理异常
    33. }
    34. }
    35. private void addToZip(ZipOutputStream zipOut, InputStream inputStream, String fileName) throws IOException {
    36. ZipEntry zipEntry = new ZipEntry(fileName);
    37. zipOut.putNextEntry(zipEntry);
    38. byte[] buffer = new byte[1024];
    39. int bytesRead;
    40. while ((bytesRead = inputStream.read(buffer)) != -1) {
    41. zipOut.write(buffer, 0, bytesRead);
    42. }
    43. zipOut.closeEntry();
    44. inputStream.close();
    45. }
    46. // 获取文件流
    47. private InputStream getStudentVideoStream() throws FileNotFoundException {
    48. // 附件信息
    49. FileInputStream inputStream = new FileInputStream("C:\\Users\\28111\\Videos\\2023-09-14 21-30-36.mkv");
    50. return inputStream;
    51. }
    52. }

    下载的结果:

    3. 设置HTTP响应头

    downloadStudentWork方法中,我们设置HTTP响应头,以便告诉浏览器该响应是一个可下载的二进制文件。我们还将文件名进行URL编码,以确保文件名中的特殊字符不会导致问题。

    4. 创建ZIP文件并添加内容

    使用Java的ZipOutputStream类,我们创建一个ZIP文件,并向其中添加学生作品的内容。在示例中,我们添加了一个假设的学生作品视频文件。

    5. 提供下载流

    我们使用StreamingResponseBody来提供下载文件的流,以便文件能够逐块传输给客户端。这样可以有效地处理大文件,而不需要将整个文件加载到内存中。

    6. 完整的示例

    以上是代码的大致结构,你可以在你的项目中实现它。请确保根据你的需求调整文件路径和名称。

    7. 测试文件下载

    最后,运行你的Spring Boot应用程序,访问/download/studentWork端点,你将能够下载学生作品的ZIP文件。

    结论

    通过使用Spring Boot,我们很容易实现了一个强大的文件下载功能。你可以根据需要扩展这个示例,添加更多的附件或自定义功能,以满足你的应用程序需求。

    希望这篇文章对你有所帮助,如果有任何问题或建议,请随时留言。


  • 相关阅读:
    vue-cli2打包完后通过调试窗口可以看到源代码
    Day9 :面向对象进阶
    漏洞分析丨HEVD-0x9.UseAfterFree[win7x86]
    Go语法之函数 defer使用
    [附源码]java毕业设计人口老龄化社区服务与管理平台
    RTT学习笔记12-串口外设和串口驱动框架
    面试打底稿③ 专业技能的第三部分
    两种风格的纯CSS3加载动画
    JAVA面试题——关于ValueOf的取值问题
    基于单向链表结构的软件虚拟定时器的设计与构建
  • 原文地址:https://blog.csdn.net/qijing19991210/article/details/132939382