文件下载核心知识点笔记
一、核心问题与解决方向
- 中文文件名乱码:需对文件名进行 URL 编码。
- 大文件内存溢出(OOM):采用分块读取(
InputStreamResource 包装流)。
- 资源泄漏:使用
try-with-resources 自动关闭 IO 资源。
- 响应头配置:通过
Content-Disposition、ContentType、ContentLength 控制下载行为。
二、关键技术点
1. 中文文件名编码
使用 URLEncoder.encode(filename, "UTF-8") 对中文文件名编码,避免浏览器下载时乱码。
2. 分块读取(防止 OOM)
通过 InputStreamResource 包装文件输入流,由框架自动处理分块传输,避免大文件一次性加载到内存。
3. 响应头配置
| 响应头 / 属性 |
作用 |
示例值 |
Content-Disposition |
控制文件下载行为,attachment 表示作为附件下载,需指定文件名。 |
attachment; filename=美女.jpg |
ContentType |
指定响应内容的媒体类型,二进制文件通用 APPLICATION_OCTET_STREAM。 |
MediaType.APPLICATION_OCTET_STREAM |
ContentLength |
指定文件的字节大小,便于前端感知下载进度。 |
文件实际字节数 |
三、Spring MVC 实现示例(优化版)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.http.InputStreamResource; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;
import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets;
@RestController public class DownloadController {
@RequestMapping("/download") public ResponseEntity<InputStreamResource> downloadFile() throws IOException { File file = new File("D:\\Aimg\\MaYi.jpg"); String originalFilename = "美女.jpg";
String encodedFilename = URLEncoder.encode(originalFilename, StandardCharsets.UTF_8);
try (FileInputStream inputStream = new FileInputStream(file)) { InputStreamResource resource = new InputStreamResource(inputStream);
return ResponseEntity.ok() .contentType(MediaType.APPLICATION_OCTET_STREAM) .contentLength(file.length()) .header("Content-Disposition", "attachment; filename=" + encodedFilename) .body(resource); } } }
|
四、关键优化说明
- 资源安全:
try-with-resources 确保文件输入流自动关闭,避免资源泄漏。
- 性能可靠:
InputStreamResource 分块传输大文件,彻底解决 OOM 风险。
- 兼容性强:
URLEncoder 处理中文文件名,兼容各类浏览器。
- 参数准确:
file.length() 保证 ContentLength 准确,提升下载体验。
通过以上配置,可实现安全、高效、兼容的文件下载功能,覆盖中文乱码、大文件处理、资源管理等核心场景。
==idea代码:==
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
| package com.example.springmvc.controller;
import com.example.springmvc.bean.Person; import org.springframework.core.io.InputStreamResource; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;
import java.io.FileInputStream; import java.io.IOException; import java.net.URLEncoder;
@RestController public class ResponseTestController {
@RequestMapping("/resp01") public Person resp01() { Person person = new Person(); person.setUsername("张三"); person.setPassword("1111"); person.setCellphone("222222"); person.setAgreement(false); person.setSex("男"); person.setHobby(new String[]{"足球", "篮球"}); person.setGrade("一年级"); return person; }
@RequestMapping("/download") public ResponseEntity<byte[]> download() throws IOException { FileInputStream inputStream = new FileInputStream("D:\\Aimg\\MaYi.jpg"); byte[] bytes = inputStream.readAllBytes();
String encode = URLEncoder.encode("美女.jpg", "UTF-8"); return ResponseEntity.ok() .contentType(MediaType.APPLICATION_OCTET_STREAM) .contentLength(bytes.length) .header("Content-Disposition", "attachment;filename=" + encode) .body(bytes); }
@RequestMapping("/download1") public ResponseEntity<InputStreamResource> download1() throws IOException { FileInputStream inputStream = new FileInputStream("D:\\Aimg\\MaYi.jpg");
String encode = URLEncoder.encode("美女.jpg", "UTF-8");
InputStreamResource resource = new InputStreamResource(inputStream);
return ResponseEntity.ok() .contentType(MediaType.APPLICATION_OCTET_STREAM) .contentLength(inputStream.available()) .header("Content-Disposition", "attachment;filename=" + encode) .body(resource); } }
|