我正在参加掘金「掘金·启航计划」。
前端excel导出
最近的项目中有一个小功能,后端返回一个文件流,前端把excel保存在本地即可。当时想着是一个很简单的事情,只需要生成一个 a 链接,把文件流转换一下二进制,把 a 标签的 href 属性指向这个二进制就可以了。
const blob = new Blob([res], {
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8" });
let link = document.createElement("a");
link.style.display = "none";
link.href = URL.createObjectURL(blob);
link.setAttribute("download", "指标对比.xlsx"); // 制定下载文件名
document.body.appendChild(link);
link.click();
document.body.removeChild(link); //下载完成移除元素
window.URL.revokeObjectURL(link.href); //释放掉blob对象
tips: type要跟后端返回的文件流类型一样
当时代码这样写的完全没有问题,结果用起来就是报错,报接口异常。当时百度,问同事。都说没问题,卒子后我一看报错的地方。是响应拦截器报的错。这个项目返回的数据格式必须要有deta,code。结果文件导出的接口只有一个文件流。导致响应拦截报错。
解决办法就是重新创建一个 axios 实例,不走响应拦截器。
/**
* @description: 纯净请求post处理文件流
* @param {string} url
* @param {object} params
* @param {object} options
* @return {*}
*/
export const purePost = (url: string, params: object, options: { [key: string]: any } = {}) => {
return pureRequest({
url: url,
method: 'post',
data: params,
responseType: 'arraybuffer',
headers: {
'x-token': getCookie('x-token'), // 向后台发送的token
'x-no-encrypt': true,
'Content-Type': 'application/json;charset=utf-8',
...options,
},
});
}
这里也有一个小坑,封装请求的时候要添加一个 responseType
属性,不加会导致文件导出无法打开的情况。
tips: post请求为
arraybuffer
,get请求为blob
最后前端导出文件流就搞定了。水一篇文章,拿一点奖励!☺