使用vue+Springboot+easyExecl导出文件时,在浏览器中下载的文件总是打不开,并且显示这个错误
1.我们逐步进行排查,首先看是不是后端的问题。这里附上我后端的代码
@GetMapping("/downloadTemplate")
public void download(HttpServletResponse response) throws IOException {
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
response.setHeader("Content-disposition", "attachment;filename=example.xlsx");
List<Entry> entries = new ArrayList<Entry>();
Entry entry = new Entry();
entry.setQuestion("整改方案很清楚,但酒店不愿意整改,怎么办?");
entry.setAnswer("A:升级到区域协调,及时在甲方在的微信群反馈,任何纠纷我们都不与酒店交涉。");
entry.setQuestionType("工程师问题");
entry.setDataSource("美团");
entry.setKeyword("整改,方案,不整改,不愿整改");
entry.setQuestionCategory("踏勘问题");
entry.setEquipmentCategory("流程问题");
entries.add(entry);
EasyExcel.write(response.getOutputStream(), Entry.class).registerWriteHandler(CellStyleUtils.getHorizontalCellStyleStrategy()).
sheet("sheet1").doWrite(entries);
}
在后端的代码中,使用easyExecl将响应的数据转为了流的形式,这个代码看起来没有问题,我们使用localhost+downloadTemplate的方式进行请求接口,这里我就不演示了,最终的结果是成功下载,并且可以正常打开,这证明我们后端的代码没有问题。
2.我们看一眼返回的响应数据,在控制台打印
再看我们前端的代码
request(downloadTemplate, METHOD.GET,null,{responseType: 'blob'}).then(res => {
console.log(res)
if (res.status === 200) {
let blob = new Blob([res.data], {type: res.data.type})
const fileName = 'ProductTemplateCopy.xlsx';
let downloadElement = document.createElement('a')
let href = window.URL.createObjectURL(blob); //创建下载的链接
downloadElement.href = href;
downloadElement.download = fileName; //下载后文件名
document.body.appendChild(downloadElement);
downloadElement.click(); //点击下载
document.body.removeChild(downloadElement); //下载完成移除元素
window.URL.revokeObjectURL(href); //释放blob
this.$message.info('导出成功')
}
请求接口时,我们设置返回的应该是blob文件,再看我们第二步,可以看到在这里blob文件被硬生生转换成了json格式的代码。然后下载后的文件就损坏报错。
为什么会出现这种情况呢?
文件发生了变化,他是在哪变化的?因此我想到了是响应的时候某一个地方应该进行了处理,在此,我使用的是antd-vue-admin这个模板,其中的mockjs会对所有的前端请求进行一个拦截处理,就会对blob产生影响。所以我尝试将src/main中的mock注释
注释之后,重新尝试请求接口,最终成功了。下载的文件也可以打开了。因此本次bug出现的原因是mock处理导致blob发生了变化。