比对模式的检测报告生成和下载
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { ElNotification } from "element-plus";
|
||||
import type { AxiosResponse } from "axios";
|
||||
|
||||
/**
|
||||
* @description 接收数据流生成 blob,创建链接,下载文件
|
||||
@@ -8,6 +9,55 @@ import { ElNotification } from "element-plus";
|
||||
* @param {Boolean} isNotify 是否有导出消息提示 (默认为 true)
|
||||
* @param {String} fileType 导出的文件格式 (默认为.xlsx)
|
||||
* */
|
||||
/**
|
||||
* 从 Content-Disposition 头解析文件名
|
||||
*/
|
||||
const getFileNameFromContentDisposition = (contentDisposition: string | undefined | null): string | null => {
|
||||
if (!contentDisposition) return null;
|
||||
|
||||
// 优先匹配 filename*=UTF-8'' 格式(RFC 5987)
|
||||
const filenameStarRegex = /filename\*\s*=\s*UTF-8''([^;]+)/i;
|
||||
const starMatches = filenameStarRegex.exec(contentDisposition);
|
||||
|
||||
if (starMatches && starMatches[1]) {
|
||||
try {
|
||||
return decodeURIComponent(starMatches[1]);
|
||||
} catch (e) {
|
||||
console.warn('解码 filename* 失败:', e);
|
||||
}
|
||||
}
|
||||
|
||||
// 其次匹配 filename="文件名" 或 filename=文件名 格式
|
||||
const filenameRegex = /filename\s*=\s*([^;]+)/i;
|
||||
const matches = filenameRegex.exec(contentDisposition);
|
||||
|
||||
if (matches && matches[1]) {
|
||||
let filename = matches[1].trim();
|
||||
|
||||
// 去除引号
|
||||
filename = filename.replace(/^["']|["']$/g, "");
|
||||
|
||||
// 尝试解码 URL 编码的文件名
|
||||
try {
|
||||
// 检查是否包含 URL 编码字符
|
||||
if (filename.includes('%') || filename.includes('UTF-8')) {
|
||||
// 处理可能的 UTF-8 前缀
|
||||
if (filename.startsWith("UTF-8''") || filename.startsWith("utf-8''")) {
|
||||
filename = filename.substring(7);
|
||||
}
|
||||
filename = decodeURIComponent(filename);
|
||||
}
|
||||
} catch (e) {
|
||||
// 如果解码失败,返回原始文件名
|
||||
console.warn('解码文件名失败,使用原始值:', e);
|
||||
}
|
||||
|
||||
return filename;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
export const useDownload = async (
|
||||
api: (param: any) => Promise<any>,
|
||||
tempName: string,
|
||||
@@ -39,6 +89,73 @@ export const useDownload = async (
|
||||
document.body.removeChild(exportFile);
|
||||
window.URL.revokeObjectURL(blobUrl);
|
||||
} catch (error) {
|
||||
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @description 支持服务器文件名的下载方法,会从 Content-Disposition 头获取文件名
|
||||
* @param {Function} api 导出表格的api方法 (必传)
|
||||
* @param {String} fallbackName 备用文件名,当服务器未提供时使用 (可选)
|
||||
* @param {Object} params 导出的参数 (默认{})
|
||||
* @param {Boolean} isNotify 是否有导出消息提示 (默认为 true)
|
||||
* @param {String} fallbackFileType 备用文件格式,当服务器未提供时使用 (默认为.xlsx)
|
||||
*/
|
||||
export const useDownloadWithServerFileName = async (
|
||||
api: (param: any) => Promise<AxiosResponse<Blob> | any>,
|
||||
fallbackName: string = "",
|
||||
params: any = {},
|
||||
isNotify: boolean = true,
|
||||
fallbackFileType: string = ".xlsx"
|
||||
) => {
|
||||
if (isNotify) {
|
||||
ElNotification({
|
||||
title: "温馨提示",
|
||||
message: "如果数据庞大会导致下载缓慢哦,请您耐心等待!",
|
||||
type: "info",
|
||||
duration: 3000
|
||||
});
|
||||
}
|
||||
try {
|
||||
const res = await api(params);
|
||||
|
||||
// 检查响应是否包含 data 属性(AxiosResponse)还是直接是 Blob
|
||||
const blob = res.data ? new Blob([res.data]) : new Blob([res]);
|
||||
|
||||
// 尝试从响应头获取文件名(如果存在)
|
||||
let serverFileName: string | null = null;
|
||||
if (res.headers) {
|
||||
const headers = res.headers || {};
|
||||
const contentDisposition = headers['content-disposition'] || headers['Content-Disposition'];
|
||||
serverFileName = getFileNameFromContentDisposition(contentDisposition);
|
||||
}
|
||||
|
||||
// 确定最终使用的文件名
|
||||
let finalFileName: string;
|
||||
if (serverFileName) {
|
||||
finalFileName = serverFileName;
|
||||
} else if (fallbackName) {
|
||||
finalFileName = `${fallbackName}${fallbackFileType}`;
|
||||
} else {
|
||||
finalFileName = `download${fallbackFileType}`;
|
||||
}
|
||||
|
||||
// 兼容 edge 不支持 createObjectURL 方法
|
||||
if ("msSaveOrOpenBlob" in navigator) {
|
||||
return window.navigator.msSaveOrOpenBlob(blob, finalFileName);
|
||||
}
|
||||
|
||||
const blobUrl = window.URL.createObjectURL(blob);
|
||||
const exportFile = document.createElement("a");
|
||||
exportFile.style.display = "none";
|
||||
exportFile.download = finalFileName;
|
||||
exportFile.href = blobUrl;
|
||||
document.body.appendChild(exportFile);
|
||||
exportFile.click();
|
||||
// 去除下载对 url 的影响
|
||||
document.body.removeChild(exportFile);
|
||||
window.URL.revokeObjectURL(blobUrl);
|
||||
} catch (error) {
|
||||
console.error('文件下载失败:', error);
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user