POST方法与GET方法下载的区别:
-
GET用于获取数据,POST用于提交数据。但文件下载通常属于获取资源,所以理想情况下应使用GET。然而,当参数较长或包含敏感信息时,使用POST更合适。
-
对于文件下载,使用GET时,可以直接通过链接下载(例如window.open),不需要复杂的前端处理。
-
使用POST时,不能直接用链接,必须通过表单提交或AJAX请求(如本例),然后将返回的文件通过Blob方式处理并触发下载。
导出流程:通过Axios发送POST请求获取二进制Excel文件 → 创建临时URL → 模拟点击下载 → 清理资源
js
import axios from 'axios';
<Button loading={loading} type="primary" onClick={exportStatistics}>下载报表</Button>
const exportStatistics = async () => {
const baseURL = `${window.location.protocol}//${process.conf.ip}${process.conf.nginx ? '/gateway' : ''}`
const source = axios.CancelToken.source();
try {
if (!filterRef.current?.getFilterParam) {
return;
}
const filterParams = filterRef.current.getFilterParam();
setLoading(true);
const payload = JSON.stringify({
plantIdList: filterParams.plantIdList,
indexList: filterParams.indexList,
});
const response = await axios.post(
`${baseURL}/statistics/data/export`,
payload,
{
headers: {
'Content-Type': 'application/json',
Accept: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
},
responseType: 'blob', // 指定响应类型为二进制数据
cancelToken: source.token,
transformResponse: [data => data], // 禁用自动转换
},
);
const blob = response.data ? response.data : response;
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `指标统计报表_${moment().format('YYYY-MM-DD HH:mm:ss')}.xlsx`;
a.style.display = 'none';
document.body.appendChild(a);
a.click();
setTimeout(() => {
document.body.removeChild(a);
URL.revokeObjectURL(url);
source.cancel(); // 取消请求令牌
}, 100);
} catch (error) {
console.error('导出失败:', error);
} finally {
setLoading(false);
}
};
特殊处理及原因:
-
responseType: 'blob':
- 因为响应是二进制文件(Excel),所以需要将响应类型设置为
blob
,以便正确处理。
- 因为响应是二进制文件(Excel),所以需要将响应类型设置为
-
transformResponse: [data => data]:
- 默认情况下,axios会根据响应类型转换数据,但这里我们不需要转换,所以覆盖默认转换器,直接返回原始数据。
-
创建临时URL和隐藏的a标签:
- 由于我们无法直接保存来自AJAX请求的文件,因此将Blob数据转换为一个URL,并模拟点击一个下载链接来触发浏览器下载。
-
使用取消令牌:
- 允许在组件卸载等情况下取消请求,避免内存泄漏和潜在的错误。
-
setTimeout清理资源:
- 在下载开始后移除临时创建的a标签和URL,释放资源。使用setTimeout是为了确保下载已经启动。
-
错误处理:
- 捕获请求过程中可能出现的错误,例如网络问题或后端错误。
-
设置加载状态:
- 在开始请求时设置加载状态,在请求结束后(无论成功或失败)清除状态,以提供用户反馈。