java excel导出无法下载/乱码
描述:使用java进行导出excel文件,前端为vue请求。
Web(vue) => 客户端 => 服务端
出现的问题:
- 服务直接使用response流返回,客户端同样使用,出现流不能使用两次的情况
- 基于1 ,方法一:客户端接收服务端的body导出,方法二,服务只提供数据,客户端进行导出(当前采用)
- 后续按照hutool 的setContentType 写法使用浏览器链接获取是没问题的,但是服务有很多安全校验之类的还是得走自己封装的接口。而axios返回的默认数据类型导致excel会出现乱码,需要指定接收blob
后台 java
相关链接:Excel工具: hutool
@GetMapping(value = "/xxxxxx")
void getExcel(@RequestParam("id") Long ac,HttpServletResponse response){
//(有响应流不能用两次的异常,所以这里被调用的服务只返回数据。)
List<xxx> reportData = // 调用后台服务获取数据列表,
ExcelWriter writer = ExcelUtil.getWriter(); // 用的是糊涂工具的导出 ,用其他也是一样的操作。
// 写出
writer.write(reportData, true);
// 这个注释的是官网的写法,如果是用浏览器链接请求的话是可以自动下载查看的,但是如果经过axios封装的请求则不行。这里采用的blob 进行传输。
// response.setContentType("application/vnd.ms-excel;charset=utf-8");
response.setContentType("octet-stream");
response.addHeader("Content-Disposition", "attachment;filename=xn_report"+ LocalDate.now().toString()+"_"+ ac + ".xls");
response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
ServletOutputStream out= null;
try {
out = response.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}finally {
writer.flush(out, true);
writer.close();
IoUtil.close(out);
}
}
前端 vue
参考原文:前端使用Blob处理后台传输的文件流
// 请求
export function getExcel(values) {
return request({
url: '/report/getXnDataExcelByActivityId',
method: 'get',
responseType: 'blob', // 这里一定要加上不然乱码
params: values
})
}
--------------------------------------------------
// 调用
getExcel(data).then((res) => {
if (!res.data) {
return;
}
// 让前端接收流转换为excel进行下载
let blob = new Blob([res.data], {
type: 'application/octet-stream'
});
let link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
let fileName = res.headers['content-disposition'].split(';')[1].split('=')[1];
fileName = decodeURIComponent(fileName);
link.download = fileName;
link.click();
});