import axios from 'axios';
import { message } from 'antd';
/**
* 下载 ZIP 文件
* @param {string} url - 下载地址
* @param {Object} params - 请求参数
* @param {string} fileName - 默认文件名
* @param {Function} onProgress - 下载进度回调
*/
export const downloadZip = async (url, data = {}, fileName = 'download.zip', onProgress = null) => {
try {
const response = await axios({
url,
method: 'post',
data,
responseType: 'blob',
headers: {
'Authorization': `Bearer ${getToken()}`, // 获取认证 token
'Cache-Control': 'no-cache',
},
onDownloadProgress: (progressEvent) => {
if (onProgress && progressEvent.total) {
const percentCompleted = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
);
onProgress(percentCompleted);
}
},
});
// 处理响应
return handleZipResponse(response, fileName);
} catch (error) {
handleDownloadError(error);
return false;
}
};
/**
* 处理 ZIP 响应
* @param {Object} response - Axios 响应对象
* @param {string} defaultFileName - 默认文件名
*/
const handleZipResponse = (response, defaultFileName) => {
// 从响应头获取文件名
const contentDisposition = response.headers['content-disposition'];
let fileName = defaultFileName;
if (contentDisposition) {
const filenameMatch = contentDisposition.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/);
if (filenameMatch && filenameMatch[1]) {
fileName = filenameMatch[1].replace(/['"]/g, '');
// 处理 UTF-8 编码的文件名
if (fileName.includes('%')) {
fileName = decodeURIComponent(fileName);
}
}
}
// 验证是否为 ZIP 文件
const contentType = response.headers['content-type'];
if (!contentType.includes('application/zip') &&
!contentType.includes('application/octet-stream')) {
throw new Error('服务器返回的不是有效的 ZIP 文件');
}
// 创建下载链接
const blob = new Blob([response.data], { type: 'application/zip' });
const downloadUrl = window.URL.createObjectURL(blob);
// 创建虚拟链接触发下载
const link = document.createElement('a');
link.href = downloadUrl;
link.setAttribute('download', fileName);
document.body.appendChild(link);
link.click();
// 清理资源
document.body.removeChild(link);
window.URL.revokeObjectURL(downloadUrl);
return {
success: true,
fileName,
fileSize: blob.size,
contentType,
};
};
/**
* 处理下载错误
* @param {Error} error - 错误对象
*/
const handleDownloadError = (error) => {
if (axios.isCancel(error)) {
console.log('下载已取消');
return;
}
// 处理 Blob 类型的错误响应
if (error.response?.data instanceof Blob) {
const reader = new FileReader();
reader.onload = () => {
try {
const errorResponse = JSON.parse(reader.result);
message.error(errorResponse.message || 'ZIP 文件下载失败');
} catch (e) {
message.error('服务器返回了无效的错误信息');
}
};
reader.readAsText(error.response.data);
return;
}
// 处理其他错误
console.error('ZIP 下载错误:', error);
let errorMessage = '下载失败';
if (error.response) {
switch (error.response.status) {
case 401:
errorMessage = '未授权,请登录';
break;
case 403:
errorMessage = '权限不足,无法下载';
break;
case 404:
errorMessage = '文件不存在';
break;
case 500:
errorMessage = '服务器错误';
break;
default:
errorMessage = `下载失败 (状态码: ${error.response.status})`;
}
} else if (error.request) {
errorMessage = '请求超时或无响应';
} else {
errorMessage = `请求错误: ${error.message}`;
}
message.error(errorMessage);
};
/**
* 获取认证 token
*/
const getToken = () => {
const userInfo = JSON.parse(localStorage.getItem('x-userInfo') || '{}');
return userInfo.token || '';
};
02-24
1万+

03-29
9456

05-23
8943

03-03
8129

12-18
7849

11-22
4697

11-02
4643

11-12
4367

09-05
4157

07-13