使用阿里EasyExcel下载excle的简单样例记录,包含前后端核心代码,主要记录中文文件名称乱码问题的处理。
EasyExcle的使用不再多做记录,EasyExcel教程-阿里云开发者社区 (aliyun.com)中内容详细。
在通过后端进行文件下载时,经常会遇到乱码问题,网上可以搜索到多种解决方案,尝试了多种方式后记录下如下一种可行方案的核心代码。
后端代码:
@GetMapping("download")
public void download(HttpServletResponse response) throws IOException {
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
// 这里URLEncoder.encode可以防止中文乱码,所有通过后端的文件下载都可以如此处理
String fileName = URLEncoder.encode("数据写出", "UTF-8");
//建议加上该段,否则可能会出现前端无法获取Content-disposition
response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
EasyExcel.write(response.getOutputStream(), DownloadData.class).sheet("模板").doWrite(data());
}
前端可以采用两种方式执行下载:
第一种:
直接使用window.location.href = "downloadUrl";
该方式直接通过浏览器的对response的内容进行处理,浏览器会对文件名称进行相应的decode,从而保证我们下载的文件名称正常
第二种:
通过ajax请求,异步调用下载方法。
通过该方式下载,如果采用swaggerui或者postman测试会发现返回的header中filename为encode后的名称,点击swaggerui中的下载下载后的文件名称也是未decode的名称,很多文章将这归咎为swagger导致的但没有说明是怎么导致的,我也在这困惑很久。现在我猜测是他们通过swagger测试下载的文件名称错误,后续直接采用了上面的第一种方法,成功下载,便将原因归咎到了swagger中。如下是vue axios异步下载的一种方案:
mounted() {
axios({
method: "get",
url: "http://localhost:9104/download",
responseType: "arraybuffer"
}).then(response => {
//通过header中获取返回的文件名称
let fileName = response.headers['content-disposition']
.split(";")[1].split("filename=")[1]
let blob = new Blob([response.data], { type: "application/vnd.ms-excel" })
let downloadElement = document.createElement("a")
var href = window.URL.createObjectURL(blob)
downloadElement.href = href
//指定下载的文件的名称,切记进行decode
downloadElement.download = decodeURI(fileName)
document.body.appendChild(downloadElement)
downloadElement.click()
//移除临时创建对象,释放资源
document.body.removeChild(downloadElement)
window.URL.revokeObjectURL(href)
});
}
一次踩坑记录,如果错误还望指正。
注意:如上代码前端为Chrome浏览器,其他浏览器并未验证。