环境:React 16.8.6 + umi-request
需求背景:原来直接操作dispatch调接口就可以下载导出文件了,但是由于服务端上传文件的接口不知道为啥没有开放出来,就没办法转成链接传给前端了,所以前端这边只能相应的改一下了。
一开始,我也很懵,因为之前并没有获取过文件流,都是服务端转成链接给前端的,所以就去网上查找资料,去尝试。终于,功夫不负有心人,终于成功获取到文件并且下载下来,下面就记录一下我的方法吧。
具体要怎么修改呢?
假如我们继续用dispatch的方法继续调用接口,首先项目请求的response就通不过(项目统一配置了umi-request,而且默认返回的是json格式),而且接口返回的是文件流乱码(如下图),还需要对数据进行处理一下。
这个时候就需要我们稍稍判断调整一下request里面的返回值格式。
request.interceptors.response.use(async response => {
// 获取Content-Disposition
const disposition = response.headers.get('Content-Disposition');
if (disposition) {
return {
// 将二进制的数据转为blob对象,这一步是异步的因此使用async/await
blob: await response.blob(),
// 处理Content-Disposition,获取header中的文件名
fileName: decodeURI(disposition.split(';')[1].split('filename=')[1]),
};
}
// 原先直接从这里开始判断,是否是json
const data = await response.clone().json();
if (data.code !== 200) {
// TODO...
}
return response;
});
这里加好之后,我发现接口虽然调用成功了,但是页面一直会有个空的报错弹窗,检查了下代码,发现是request配置里加了统一的业务判断,默认了请求成功会返回一个code=200,这个就没办法了,只能另外写一个request了。
于是我就直接在函数里引用request方法:
const res = await request(
'api address', {
baseUrl: 'api域名',
method: 'POST',
data: { ...请求传参 },
responseType: 'blob',
credentials: 'include', // 默认请求是否带上cookie
});
这样,接口就调用成功了,而且不会有额外的错误提示弹窗。接下来需要将获取到的文件下载到本地:
let blob = new Blob([res.blob], {
type: 'application/vnd.ms-excel', // excel格式文件
});
let link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = 'coupon_settlement_list.xlsx'; // 设置下载的文件名称
link.target = '_blank';
link.click();
window.URL.revokeObjectURL(blob);
至此,react项目通过post请求获取文件流并且下载到本地的功能就结束了。