使用 Spring MVC 的 ResponseEntity 传入文件的字节码即可实现下载功能,不用往HttpServletResponse response
的输出流写字节了。
public class BasicController {
protected ResponseEntity<byte[]> getFile(String fileName, byte[] dataArray) throws Exception {
fileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.toString());
HttpHeaders headers = new HttpHeaders();
headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
headers.add("Content-Disposition", "attachment; filename=\"" + fileName + "\"; filename*=utf-8''" + fileName);
headers.add("Pragma", "no-cache");
headers.add("Expires", "0");
return ResponseEntity
.ok()
.headers(headers)
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.body(dataArray);
}
protected ResponseEntity<byte[]> getExcelFile(String fileName, byte[] dataArray) throws Exception {
// fileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.toString());
// Safari 和 Chrome 都可以正常下载包含中文文件名的 excel 文件
fileName = new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
HttpHeaders headers = new HttpHeaders();
headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
headers.add("Content-Disposition", "attachment; filename=\"" + fileName + "\"; filename*=utf-8''" + fileName);
headers.add("Pragma", "no-cache");
headers.add("Expires", "0");
headers.add("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
return ResponseEntity
.ok()
.headers(headers)
.body(dataArray);
}
}
getFile
方法在 Safari 浏览器不能正常下载 Excel 文件,下载的是一个后缀名为 .dms
文件。getExcelFile
指定 Excel 的 MIME 类型,并将文件名编码为 ISO_8859_1
,兼容 Chrome 和 Safari 的下载。
@RestController
public class FileProcessController extends BasicController {
@GetMapping("/test/download")
public ResponseEntity<byte[]> downloadFile(d) throws Exception {
// 得到文件的字节数组
byte[] dataArray = getData();
return this.getExcelFile("excel-文件下载.xlsx", dataArray);
}
}
在浏览器里模拟一下:
Spring MVC 文件下载测试: <a href="http://localhost:8080/test/download">点击下载</a>
我当时在项目里测试的时候,因为没有 Cookie,请求后端则没有权限,
在 Chrome 或 Safari 开发者工具的 Console 用:
document.cookie="COOKIE_KEY=COOKIE_VALUE";
设置请求 Cookie。
参考:解决各大浏览器下载文件名显示不正确的情况
java实现浏览器下载文件,并解决兼容各浏览器的乱码与后缀问题
Spring MVC 文件下载及中文文件名乱码解决