Spring MVC 优雅下载和文件名正常显示

使用 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 文件下载及中文文件名乱码解决

猜你喜欢

转载自blog.csdn.net/jiaobuchong/article/details/84641668