1. void 方法,使用 HttpServletResponse 进行文件下载:
java
@PostMapping("/downloadFile")
public void downloadFile(HttpServletResponse response) {
// 实现文件下载逻辑
byte[] fileData = /* 从某处获取文件数据 */;
try (OutputStream outputStream = response.getOutputStream()) {
// 将文件数据通过输出流写入响应
outputStream.write(fileData);
outputStream.flush();
} catch (IOException e) {
// 处理异常
}
}
优点:
简单直接: 实现起来简单,不需要额外的封装和返回对象。 流式传输: 可以直接将文件内容流式传输到响应中,适合大文件下载。
缺点:
控制有限: 对HTTP响应的控制有限,例如,可能更难以设置特定的HTTP头部或以标准化的方式处理错误。
单元测试难度较大: 直接与HttpServletResponse交互可能使单元测试难度较大。
适用场景: 简单的文件下载场景,不需要复杂的控制和处理。
2. ResponseEntity 方法
java
@GetMapping("/downloadFile")
public ResponseEntity<org.springframework.core.io.Resource> downloadFile() {
byte[] fileData = /* 从某处获取文件数据 */;
InputStreamResource inputStreamResource = new InputStreamResource(new ByteArrayInputStream(fileData));
HttpHeaders headers = new HttpHeaders();
// 设置响应头
HttpStatus statusCode = /* 设置状态码 */;
return new ResponseEntity<>(inputStreamResource, headers, statusCode);
}
优点:
更灵活: 可以更好地控制HTTP响应,设置头部、状态码,并以标准化的方式处理错误。
可测试性: 更易于进行单元测试,因为它返回标准的响应实体。
缺点:
相对复杂: 代码可能相对复杂,需要创建Resource并设置额外的头部。
适用场景:
需要更多对HTTP响应的控制、标准化的错误处理和更好的可测试性。
3. StreamingResponseBody 方法:
java
@GetMapping("/downloadFile")
public StreamingResponseBody downloadFile() {
return outputStream -> {
byte[] fileData = /* 从某处获取文件数据 */;
InputStream inputStream = new ByteArrayInputStream(fileData);
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
inputStream.close();
};
}
优点:
流式传输: 允许直接将文件内容流式传输到响应中,对于大文件可能更为内存高效。
简单性: 相对较简单,不需要创建额外的响应实体对象。
缺点:
相对较少的控制: 对HTTP响应的控制相对较少,可能需要额外处理头部等信息。
适用场景:
大文件下载,需要较高的性能和较小的内存开销。
建议:
- 如果简单性和流传输效率至关重要,而且对HTTP响应的精细控制不是必需的话,第一种方法可能更适合。
- 如果需要更多对HTTP响应的控制、标准化的错误处理和更好的可测试性,那么使用ResponseEntity的第二种方法更为推荐。
- 对于大文件下载,或者需要更高性能和较小内存开销的情况,可以考虑使用StreamingResponseBody的第三种方法。