永远不要把希望寄托给未来的自己,他比现在的你承受更大的压力。
很多时候我们会遇到这样的需求:实现导出功能,根据用户选择导出报表。
没错,我也遇到了,当你拥有一个良心后端时,他会选择返回一个下载地址,然后前端通过访问地址就可以下载该文件,简单快捷又方便;亦或者返回一个文件id,通过固定的下载接口去下载文件,也非常的亲民易懂。
但是很不巧,今天我的后端选择给我返回了一串文件流,就像这样 ↓
当遇到这种情况的时候,前端选手就需要自己将文件流转为Excel文件再下载。
方法一
首先我们在写请求的时候,需要对响应类型限制,
-
在请求配置里写上
responseType: "blob"
; -
获取到响应的文件流
-
利用
Blob
构造函数新建一个Blob
对象,并传入文件流对象和文件类型(本次为Excel),更深入内容可以查阅文档,MDN-Blob; -
用
window.URL.createObjectURL
创建一个新的URL对象,文档:URL.createObjectURL(); -
下载
// get请求
axios
.get(
`后台给的url`,
{
params: 请求参数,
responseType: "blob" // 添加响应类型
})
.then(res => {
let { data } = res; // 获取文件流
let blobObj = new Blob([data], { type: "application/vnd.ms-excel" }); // 新建 Blob 对象
let url = window.URL.createObjectURL(blobObj); // 创建 URL 对象
window.location.href = url;
});
};
// post请求同理
axios
.post(
`后台给的url`,
body参数,
{
params: url参数,
responseType: "blob"
})
.then(res => {
window.location.href = window.URL.createObjectURL(new Blob([res.data], { type: "application/vnd.ms-excel" }));
});
};
复制代码
成功解决文件流转Excel的问题,但是这种方式有一个比较明显的弊端,那就是下载下来的Excel文件名称是这个Blob
对象的url,不能固定。
方法二
这种方法巧妙的运用了a
标签来进行下载文件,可以实现对文件名进行限定,但是每次用完记得都要把创建的a
清除。,话不多说,直接贴代码。
// get请求
axios
.get(
`后台给的url`,
{
params: 请求参数,
responseType: "blob" // 添加响应类型
})
.then(res => {
let { data } = res; // 获取文件流
let blobObj = new Blob([data], { type: "application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" }); // 新建 Blob 对象
let url = window.URL.createObjectURL(blobObj); // 创建 URL 对象
let downloadLink = document.createElement('a'); // 创建 a 元素
downloadLink.style.display = 'none'; // 隐藏链接
downloadLink.download('某某报表.xls');
downloadLink.href = url; // 添加下载地址
document.body.appendChild("downloadLink"); // 添加 a 元素
downloadLink.click(); // 点击下载
document.body.removeChild("downloadLink"); // 移出 a 元素
});
};
复制代码
第二种方法中post
请求也同理,这里就不在赘述了
注意:由于a
标签的download有同源策略,如果不同源,会下载失败哦~