之前因为懒,异步请求的下载都是直接写在 a 标签里,请求权限让后端做特殊处理判断,就像这样
<a href="getRequestUrl"> 点击下载 </a>
现在觉得这样处理不太好,一个是后端权限要做单独判断,另一个是如果调用接口报错就没办法处理了,研究之后修改了一下,项目用了 axios 这个 lib,所以是针对 axios 的 request 和 response 做了修改,不过对于原生写法和其他库,原理是一样的
1. 将请求的 responseType 设置为 blob
function exportData(p) {
return axios({
url: '/data/export',
method: 'get',
params: p,
responseType: 'blob'
});
}
2. 对 response 进行处理
因为项目里用了 response 拦截器来处理响应,所以我在拦截器里做了处理,也可以单独处理。
axios.interceptors.response.use(
response=> {
// ...
// Blob 类型处理
let checkType = response.config.responseType;
if(checkType === "blob" && res.type === 'application/octet-stream') { // 正常下载时直接返回响应数据
return response.data
} else if(checkType === "blob" && res.type === 'application/json') { // 请求出错时,接口返回的内容是 json,于是将 blob 中的内容取出
let reader = new FileReader();
reader.onload = function(event){
let content = reader.result; // blob 中的内容
Message({message: JSON.parse(content).desc,
type: 'error',
duration: 5 * 1000
})
};
reader.readAsText(response.data);
return Promise.reject('error')
}
// ...
},
error => {// ...}
)
3.html 页面自动开始下载
exportData(para).then(res => {
let content = res;
let aTag = document.createElement('a');
let blob = new Blob([content]);
aTag.download = 'Datas.xlsx'; // 也可以让后端设置文件名,通过 headers 返回
aTag.href = URL.createObjectURL(blob);
aTag.click();
URL.revokeObjectURL(blob);
}).finally(() => {})
参考博客:https://www.cnblogs.com/coder…