导出Excel时,遇到后端返回文件流怎么办...

永远不要把希望寄托给未来的自己,他比现在的你承受更大的压力。

很多时候我们会遇到这样的需求:实现导出功能,根据用户选择导出报表。

没错,我也遇到了,当你拥有一个良心后端时,他会选择返回一个下载地址,然后前端通过访问地址就可以下载该文件,简单快捷又方便;亦或者返回一个文件id,通过固定的下载接口去下载文件,也非常的亲民易懂。

但是很不巧,今天我的后端选择给我返回了一串文件流,就像这样 ↓

image.png

当遇到这种情况的时候,前端选手就需要自己将文件流转为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有同源策略,如果不同源,会下载失败哦~

猜你喜欢

转载自juejin.im/post/7031830627624321037
今日推荐