下载文件核心方法就是获取到文件流后,使用createObjectURL创建url再模拟标签点击下载
1.简单快速
axios(url,{
method:'post',
data: 'data',
responseType: 'blob',
}).then((res) => {
const Url = res.headers['content-disposition'];
const fileName = Url?.split(';')[1].split('filename=')[1] || '文件';
const blob = new Blob([res.data]);
const blobUrl = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.download = fileName;
a.style.display = 'none';
a.href = blobUrl;
a.click();
document.body.removeChild(a);
});
这种方式简单快速,但是需要后端能正确返回文件流,实际项目中会有网络错误,入参错误,权限控制等各种原因导致会返回不同的结果,需要进行处理
2.每次调用单独处理错误
axios(url, {
method: 'post',
data: 'data',
responseType: 'blob',
}).then(res => {
if (res.headers['content-type'].includes('json')) {
// 正常应该返回文件流,content-type为json的时候,说明下载出错了,但是请求的时候设置了 responseType: 'blob',
// 不能按照普通的请求方式处理返回的数据,需要转化一下
// const text = await (new Response(res)).text(); 考虑到兼容性暂不使用此API
const reader = new FileReader();
reader.readAsText(res.data);
reader.onload = (readRes: any) => {
const result = JSON.parse(readRes.target.result);
// message.error(result?.message);
};
} else {
const Url = res.headers['content-disposition'];
const fileName = Url?.split(';')[1].split('filename=')[1] || '文件';
const blob = new Blob([res.data]);
const blobUrl = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.download = fileName;
a.style.display = 'none';
a.href = blobUrl;
a.click();
a.parentNode?.removeChild(a);
// message.success(`下载完成`);
}
})
.catch(err => {
console.log('%c [ err ]', 'font-size:13px; background:pink; color:#bf2c9f;', err);
message.error('下载失败,请稍候重试');
});
3.在实际项目中调用接口都有统一的api,方便进行请求前的配置后返回后的数据处理,下面是一个简单的例子,你可以参考此方法整合进你自己的项目,把错误处理和下载文件在接口上统一处理,调用的地方就不用每次都重写一遍下载方法了
export const downloadApi = (url: string, data: any, method: Method = 'POST') => {
return new Promise((resolve, reject) => {
ajax(hostUrl + url, {
method,
data: data,
responseType: 'blob',
})
.then(res => {
if (res.status === 200 && res.headers['content-type'].includes('json')) {
return Promise.reject(res);
}
const Url = res.headers['content-disposition'];
const fileName = Url.split(';')[1].split('filename=')[1];
const blobUrl = window.URL.createObjectURL(res.data);
const aElement = document.createElement('a');
document.body.appendChild(aElement);
aElement.style.display = 'none';
aElement.href = blobUrl;
aElement.download = decodeURI((/\S*/.exec(fileName))[0]);
aElement.click();
document.body.removeChild(aElement);
resolve('SUCESS');
})
.catch((err: any) => {
let headers = err?.headers;
let data = err?.data;
if (err && err.isAxiosError && err.response) {
headers = err.response.headers;
data = err.response.data;
}
if (headers?.['content-type'].includes('json')) {
const reader = new FileReader();
reader.readAsText(data);
reader.onload = (readRes: any) => {
const result = JSON.parse(readRes.target.result);
// Toast.error(result?.msg);
reject(result);
};
} else {
reject(err);
}
});
});
};