文件下载通常是使用get请求,传个id什么的,直接放在param里就好,但是我请求时需要发的数据量比较多,感觉都拼在参数里不够优雅,于是就使用了Post请求,然后测试后端能顺利接收到参数,就先把文件写好,接口返回,贴出后端代码。
@PostMapping("/export")
public void getActivityInfoByActIds(HttpServletResponse response, @RequestBody String[] actIds) throws IOException {
List<ActivityInfoVO> activityInfoByActIds =...;
//需要合并的列
int[] mergeColumnIndex = {
0,1,2};
// 从第一行后开始合并
int mergeRowIndex = 1;
String fileName = "测试" + ".xlsx";
response.setContentType("application/vnd.ms-excel;charset=utf-8");
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
EasyExcel.write(response.getOutputStream(), ActivityInfoVO.class)
.sheet("第一页")
.registerWriteHandler(new ExcelMergeUtil(mergeRowIndex, mergeColumnIndex))
.doWrite(activityInfoByActIds);
}
于是就以为OK了,高高兴兴去前端请求接口下载文件,但是慢慢发现不对劲儿,响应里有内容,但是就是不会自动下载,至此,如果大家也是使用Post请求下载文件,出现了同样的问题,至此,后端的接口是没有任何问题的,于是贴出前端的解决方法
修改之前的前端代码是这样的
export function exportActivity(obj) {
return request({
url: '/.../export',
method: 'post',
data: obj,
});
修改后的代码是这样的
export function exportActivity(obj) {
return request({
url: '.../exportActivities',
method: 'post',
data: obj,
responseType: 'blob',
}).then((res) => {
const link = document.createElement('a')
let blob = new Blob([res.data], {
type: 'application/vnd.ms-excel' })
link.style.display = 'none'
link.href = URL.createObjectURL(blob)
link.download = decodeURIComponent(res.headers['content-disposition']).split('=')[1] //下载后文件名
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
})
}
responseType: 'blob’是重点,不要忘了加,以及后续的处理,原理就是在页面Dom新建一个a标签元素,给元素的href属性设置为URL.createObjectURL(blob),然后download属性设置为下载后的文件名,然后触发a标签的点击事件,将文件下载下来,然后再Dom从移除a标签元素。
最后建议大家能用Get请求就尽量用GET请求!!!