前言
通常我们遇到的文件下载,后端都会以文件流的形式将文件传给我们,我们如何在axios或者fetch中实现文件下载的功能呢?
场景
后端返回文件流,文件名在header上,前端需要将其获取下来并且实现文件下载功能。
从上面的图片我们可以知道后端是以文件流的形式传给我们的,也可以通过headers上面的Content-Disposition上获取文件名。
区别
fetch实现
简单实现
fetch('your-file-url')
.then((response) => response.blob()) // 将响应体转为Blob对象
.then((blob) => {
// 文件名存储在'Content-Disposition'头中
const filename = response.headers.get('content-disposition').split('filename=')[1].replace(/"/g, '');
const url = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', filename); // 使用从header中获取的文件名
document.body.appendChild(link);
link.click();
link.parentNode.removeChild(link);
})
.catch((error) => console.error('Error:', error));
优雅的封装实现
// get请求下载文件封装
getFile(url: string, params: string) {
const queryString = new URLSearchParams(params).toString();
const requestUrl = queryString ? `${url}?${queryString}` : url;
let options;
const requestOptions = {
...options,
method: 'GET',
headers: {
...(options?.headers || {}),
'Content-Type': 'application/json',
},
};
return fetch(requestUrl, requestOptions)
.then(authBeforeFormate)
.then((response) => {
const { headers } = response;
headers.forEach((value, key) => {
headers[key] = value;
});
const fileStream = response.blob();
// 处理 headers
if (headers?.['content-disposition']?.indexOf('filename=') > -1) {
const filename = decodeURIComponent(
headers?.['content-disposition']
?.replace('attachment;', '')
?.replace('filename=', '')
);
const contentType = headers?.['content-type'];
return {
success: !!filename,
fileStream,
filename,
contentType,
};
}
})
.then((data) => {
// 处理data
return data;
})
.catch((err) => {
// 处理异常
return err;
});
}
如何调用
// 请求
downloadFile(params?: any) {
return http.getRequest(`your-file-url`, params);
},
const getFile = async () => {
const res = await dowloadFile()
if (res) {
const fileStream = res?.fileStream;
const fileName = res?.filename?.split('.');
const newFileName = fileName[0] + `(${state.level})` + '.' + fileName[1];
fileStream.then((resData) => {
const url = window.URL.createObjectURL(resData);
const link = document.createElement('a');
link.href = url;
link.download = newFileName
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(url);
});
message.success('下载成功');
} else {
message.error('下载失败');
}
}
axios实现
简单实现
axios({
method: 'get',
url: 'your-file-url',
responseType: 'blob',
}).then((response) => {
// 文件名存储在'Content-Disposition'头中
const filename = response.headers['content-disposition'].split('filename=')[1].replace(/"/g, '');
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', filename); // 使用从header中获取的文件名
document.body.appendChild(link);
link.click();
link.parentNode.removeChild(link);
});
优雅的封装实现
// 拦截器,统一处理未登录或者没有权限的情况
instance.interceptors.response.use(
(response: AxiosResponse) => {
const { data, headers } = response;
if (headers?.['content-disposition']?.indexOf('filename=') > -1) {
const filename = decodeURIComponent(
headers
?.['content-disposition']
?.replace('attachment;', '')
?.replace('filename=', '')
);
const contentType = headers?.['content-type'];
return {
success: !!filename,
data: {
content: data,
filename,
contentType
},
};
}
return data;
}
export const getForm = (url: string, param?: any) => {
return new Promise((resolve) => {
instance.get(url, { params: param , responseType: 'blob'}) //这里一定要用responseType: 'blob',也是和fetch的一个区别
.then(res => resolve(res))
.catch(err => resolve(err))
});
};
//请求
downloadFile(param){
return Http.getForm(`your_request_url`, param)
}
const downloadFile = async () => {
const param = {
....
}
const res = await downloadAuditLogs(param);
const fileContent = res.data.content;
const fileName = res.data.filename;
const contentType = res.data.contentType;
const blob = new Blob([fileContent], { type: contentType });
const url = window.URL.createObjectURL(blob);
const link = document.createElement('a')
link.href = url;
link.download = fileName;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(url);
}
总结
以上就是axios和fetch实现文件下载的方式,如果有不正确的地方欢迎大家指出。