实现的功能
downFile.js
文件主要实现一个 downloadFile
函数,用于从服务器下载文件。该函数支持多种请求方法(如 get
、postForm
、post
、postFile
),并根据不同的请求方法构建请求配置。同时,函数会处理加载状态,根据不同浏览器处理文件下载
,还能处理服务器返回的普通对象数据
和文件流数据
。
代码
js 代码解读复制代码import axios from 'axios';
import qs from 'qs';
import { message } from 'antd';
export default function downloadFile(
url,
parmas,
method = 'get',
callBackData, // 回调
) {
// 从响应头中提取文件名
function getFilenameFromHeaders(headers) {
const contentDisposition = headers['content-disposition'];
if (!contentDisposition) return '';
const [, name] = contentDisposition.split(';');
const [, fileName] = name.split('filename=');
return decodeURIComponent(fileName.trim());
}
// 该函数用于处理文件下载,根据浏览器类型(是否为 IE)采用不同的下载方式。该函数也可以提取为一个单独的文件,比如服务端返回的是json,某些情况才需要下载的时候,可以callBackData拿到数据去做一些判断之后再进行文件下载
const download = (response) => {
const filename = getFilenameFromHeaders(response.headers);
const blob = new Blob([response.data]);
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(blob, filename);
} else {
const downloadElement = document.createElement('a');
const href = window.URL.createObjectURL(blob);
downloadElement.href = href;
downloadElement.download = filename;
document.body.appendChild(downloadElement);
downloadElement.click();
document.body.removeChild(downloadElement);
window.URL.revokeObjectURL(href);
}
};
// 使用对象映射来返回不同请求的config参数
const methodConfigMap = {
get: (getUrl, getParmas) => ({
method: 'get',
url: `${getUrl}?${qs.stringify(getParmas)}`,
responseType: 'blob',
}),
postForm: (getUrl, getParmas) => ({
method: 'post',
url: `${getUrl}`,
data: qs.stringify(getParmas),
responseType: 'blob',
}),
post: (getUrl, getParmas) => ({
method: 'post',
url: `${url}`,
data: { ...getParmas },
responseType: 'blob',
}),
postFile: (getUrl, getParmas) => ({
method: 'post',
url: `${url}`,
data: getParmas,
responseType: 'blob',
}),
};
const config = methodConfigMap[method]?.(url, parmas) || {};
axios(config)
.then((response) => {
const reader = new FileReader();
reader.readAsText(response.data, 'utf-8');
reader.onload = (e) => {
try {
// 是普通对象数据
const jsonData = JSON.parse(e.target.result);
callBackData && callBackData(jsonData);
message.error(jsonData.message || jsonData.msg);
} catch (err) {
// 是流文件直接下载
callBackData && callBackData();
download(response);
}
};
})
.catch((err) => {
message.error(err.message);
});
}
应用场景
比如业务中的批量导出,上传文件之后服务端返回给前端的结果为文件流(这里可能是上传结果异常数据)。
使用实例
- 直接通过服务端提供的url下载
js 代码解读复制代码import downloadFile from '@utils/downFile';
// 批量导出
const batchExport = useCallback(() => {
const url = 'api/export.do';
// 有选中的数据导出选中的数据,没有选中的数据导出全部
const param = { id, detailIds: selectedkeys.length === 0 ? '' : selectedkeys.join(',') };
downloadFile(url, param, 'postForm');
}, [dispatch, id, selectedkeys]);
2.上传文件之后,服务端直接返回一个数据流或者json,不另外提供下载接口
js 代码解读复制代码 const callBackData = useCallback(
(data) => {
setImporting(false);
closeFun();
reloadPage();
// 这里可以对data做一些判断,
// 或者是前端把文件暂存到变量,展示一个结果弹窗,让用户点击的时候执行download函数并把暂存的文件流作为参数传递给download函数
if (data?.code === 900) {
message.success('导入成功');
}
},
[closeFun, reloadPage],
);
// 导入(上传)
const importFile = useCallback(() => {
setImporting(true);
const params = new FormData();
params.append('file', fileInfo);
downloadFile(
'api/batchImportToPaid.do',
params,
'postFile',
callBackData,
);
}, [callBackData, fileInfo]);
评论记录:
回复评论: