在处理HTTP响应时,尤其是文件下载或返回自定义内容时,我们通常会依赖HttpServletResponse。代码如下:
/**
*
* 基于HttpServletResponse实现的文件下载
*/
@GetMapping("/download")
public ResponseEntity download(@RequestParam String fileName,HttpServletResponse response) throws IOException {
String filePath = "你的文件路径";
String fileDisplayName = "你的文件显示名称";
try (FileInputStream fileInputStream = new FileInputStream(filePath);
OutputStream outputStream = new BufferedOutputStream(response.getOutputStream())) {
response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + URLEncoder.encode(fileDisplayName, StandardCharsets.UTF_8.toString()));
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = fileInputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
return ResponseEntity.ok().build();
} catch (IOException e) {
log.error("文件下载出错: {}", e.getMessage());
throw new RuntimeException("文件下载失败", e);
}
}
然而,随着Servlet 5.0及更高版本的发布,javax.servlet.http.HttpServletResponse已被移到jakarta.servlet.http.HttpServletResponse命名空间下。这在维护兼容性时可能会造成困扰。以下是一种使用Spring框架的ResponseEntity来解决这个问题的方法:
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.http.HttpStatus;
/**
* 使用ResponseEntity实现
*/
@GetMapping("/download")
public ResponseEntity<byte[]> serveFileDownload(String fileName) throws IOException {
String filePath = "你的文件路径";
try (FileInputStream fileStream = new FileInputStream(filePath)) {
byte[] fileBytes = new byte[fileStream.available()];
fileStream.read(fileBytes);
return ResponseEntity
.status(HttpStatus.OK) // 设置响应状态码
.header("Content-Disposition", "attachment;filename=" + fileName)
.contentType(MediaType.APPLICATION_OCTET_STREAM) // 指定内容类型,适用于任意二进制数据
.body(fileBytes); // 将文件内容作为响应体
} catch (IOException e) {
log.error("文件读取或下载过程中发生错误", e);
throw new RuntimeException("文件下载失败", e); // 可自定义异常处理策略
}
}
ResponseEntity是Spring MVC提供的一个类,它允许你完整地控制HTTP响应,包括状态码、头部和响应体。它不需要对Servlet API有直接依赖,因此可以避免因Java版本或Servlet版本差异引发的兼容性问题。使用try-with-resources语句确保了FileInputStream的正确关闭,提高了代码的可读性和安全性。 对于依赖HttpServletResponse的公共组件或工具,建议逐步迁移到使用ResponseEntity,以确保对Spring Boot 2、3以及不同Java版本(如JDK 8和11+)的支持。这样,你无需根据不同的环境编写分支代码,从而简化了维护工作。