项目的需求, 点击导出下载一个excel文件,之前以为跟以前一样点击一个链接就给我下载一个文件.这次结果不一样了,后端给我一个接口,我请求接口之后返回的是这样的东西
跟之前的数据接口完全不一样了.第一次遇到
查看了网上各种情况:
第一步: responseType: 'arrayBuffer' 这个一定要
第二步:
let filename = '';
const disposition = response.headers.get('Content-Disposition');
if (disposition && disposition.includes('attachment')) {
const filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
const matches = filenameRegex.exec(disposition);
if (matches != null && matches[1]) {
filename = matches[1].replace(/['"]/g, '');
}
}
这有两个问题:
-
最开始response.headers.get('Content-Disposition') 是没有值的, 这是因为后端没有把这个Content-Disposition暴露出来允许前端获取. 参考文章 blog.csdn.net/PGguoqi/art… 按照文章后端处理一下, 这里就可以获取到Content-Disposition从而就可以解析出filename了
-
因为这个是文件名,很有可能是含有中文的, 所有有可能是看起来是乱码,像这样:
有详细的原因: 参考my.oschina.net/pingpangkua…
我们是后端用urlencode处理一下,前端用decodeURI(fileName)解析这样就对了
第三步:
const link = document.createElement('a');
response?.blob().then((res: any) => {
const blob = new Blob([res], { type: 'application/x-xls' });
const fileName = decodeURI(filename);
link.style.display = 'none';
link.href = URL.createObjectURL(blob);
link.setAttribute('download', fileName);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
});
用Blob生成一个链接再赋值给a标签的href 模拟一个点击事件,就在浏览器现成下载了 我这里用的response?.blob().then 我看网上其他人都是直接res.data 难道是跟我们responseType不同有关系吗? 他们建议是responseType='blob' 我试过,但是还是一样的
我这里的blob()是在reponse的__proto__里面
最后就完成的这个看起来简单的需求.
完整代码:
/** 请求返回统一拦截 */
request.interceptors.response.use(
async (response: Response, options: RequestOptionsInit) => {
// 以二进制文件流的方式下载文件
if (options.responseType === 'arrayBuffer') {
let filename = '';
const disposition = response.headers.get('Content-Disposition');
if (disposition && disposition.includes('attachment')) {
const filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
const matches = filenameRegex.exec(disposition);
if (matches != null && matches[1]) {
filename = matches[1].replace(/['"]/g, '');
}
}
const link = document.createElement('a');
response?.blob().then((res: any) => {
const blob = new Blob([res], { type: 'application/x-xls' });
const fileName = decodeURI(filename);
link.style.display = 'none';
link.href = URL.createObjectURL(blob);
link.setAttribute('download', fileName);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
});
return { errCode: 0, data: [] };
}
const res = await response.clone().json();
const { errCode, data } = res;
if (errCode === '401' || errCode === '1110001') {
// token 失效重新登录
// handleTokenInvalid();
// 清空当前所有的弹窗
HxDrawer.destory();
history.push('/login');
return {
code: '0',
data,
errCode,
msg: '登录已失效,请重新登录!',
};
}
return {
...res,
data: handleNullData(data),
};
},
);