1.问题
导出二进制流文件时出现问题
2.分析
前端可以接收二进制流文件,但是不能处理,所以打印出数据看起来是乱码,因此需要前端先指定返回数据类型,和后端相同则可以正常显示
3.上对应vue文件导出函数的代码
// 导出
async exportData() {
let data = await exportxls(this.form);
// console.log(data instanceof Blob);
let fileName = "预约记录";
if (!data) {
this.$message.error("文件下载失败");
return;
}
if (typeof window.navigator.msSaveBlob !== "undefined") {
window.navigator.msSaveBlob(data, fileName + ".xlsx");
} else {
let url = window.URL.createObjectURL(data);
let link = document.createElement("a");
// link.target = "_blank";
link.style.display = "none";
link.href = url;
link.download = fileName + ".xlsx" || ""; // HTML5新增的属性
document.body.appendChild(link);
link.click(); // 点击下载
document.body.removeChild(link); // 下载完成移除元素
window.URL.revokeObjectURL(url); //释放掉blob对象
}
},
注意:在创建url时,要看后端返回的具体是什么,如果本来就是Blob实例,就不用再去new Blob()创建实例了,直接用返回的data。
4.上request.js的部分代码
在响应拦截器中和封装的请求函数中需要根据自身使用的request.js进行自己调整,但思路相同
service.interceptors.response.use(
res => {
if(res.data instanceof Blob){
return res.data
}
if (res.data.code === 0) {
return res.data;
} else if (res.data.code === 401) {
showMessage.error('登录过期');
router.push('/login')
} else {
showMessage.error(res.data.msg);
return res.data
}
},
() => {
showMessage.error('网络请求失败,反馈给客服');
}
);
我们统一的是data.code === 0为响应成功,但是对于二进制流需单独处理
const post = (url, data, config = {}) => {
config.url = url
config.data = data
config.method = 'post'
if(url === '/xls/FileDownload/BssOrder') {
config.responseType = 'blob'
}
// config.responseType = resType
return service(config)
}
这里封装的post请求函数,做的处理是判断当前url,如果请求的路径是导出所对应的url,则对当前请求,将responseType设为“blob”,这样处理不会对其他请求造成影响(这里还有其他方法的,我之前用的是其他一种方法,欢迎大家评论)