refactor: 优化 useDownload 函数,如果指定了文件名则直接使用

This commit is contained in:
2025-08-10 12:18:51 +08:00
parent 82cb66e112
commit 986c03e69f

View File

@@ -1,49 +1,58 @@
import { Message, Notification } from '@arco-design/web-vue' import { Message, Notification } from '@arco-design/web-vue'
/** /**
* @description 接收数据流生成 blob创建链接下载文件 * @description 接收数据流生成 blob创建链接下载文件
* @param {Function} api 导出表格的api方法 (必传) * @param {Function} api 导出表格的api方法 (必传)
* @param {string} tempName 导出的文件名 (必传) * @param {string} fileName 导出的文件名 (可选,例如:导出数据.xlsx默认从响应头或时间戳生成)
* @param {object} params 导出的参数 (默认{})
* @param {boolean} isNotify 是否有导出消息提示 (默认为 true)
* @param {string} fileType 导出的文件格式 (默认为.xlsx) * @param {string} fileType 导出的文件格式 (默认为.xlsx)
* @param {boolean} isNotify 是否显示导出提示消息 (默认为 false)
* @returns {Promise<void>} 无返回值
*/ */
interface NavigatorWithMsSaveOrOpenBlob extends Navigator { interface NavigatorWithMsSaveOrOpenBlob extends Navigator {
msSaveOrOpenBlob: (blob: Blob, fileName: string) => void msSaveOrOpenBlob: (blob: Blob, fileName: string) => void
} }
export const useDownload = async (api: () => Promise<any>, isNotify = false, tempName = '', fileType = '.xlsx') => { export const useDownload = async (api: () => Promise<any>, fileName = '', fileType = '.xlsx', isNotify = false) => {
try { try {
const res = await api() const res = await api()
if (res.headers['content-disposition']) { if (!fileName) {
tempName = decodeURI(res.headers['content-disposition'].split(';')[1].split('=')[1]) if (res.headers['content-disposition']) {
} else { // 从响应头提取文件名
tempName = tempName || new Date().getTime() + fileType fileName = decodeURI(res.headers['content-disposition'].split(';')[1].split('=')[1])
} else {
// 时间戳生成
fileName = new Date().getTime() + fileType
}
} }
if (isNotify && !res?.code) { if (isNotify && !res?.code) {
Notification.warning({ Notification.warning({
title: '温馨提示', title: '温馨提示',
content: '如果数据庞大会导致下载缓慢哦,请您耐心等待!', content: '如果数据庞大会导致下载缓慢哦,请您耐心等待!',
}) })
} }
if (res.status !== 200 || res.data == null || !(res.data instanceof Blob)) { // 验证响应数据
Message.error('导出失败,请稍后再试!') if (res.status !== 200 || !res.data || !(res.data instanceof Blob)) {
Message.error('导出失败:无效的响应数据')
return return
} }
const blob = new Blob([res.data]) const blob = new Blob([res.data])
// 兼容 edge 不支持 createObjectURL 方法 // 兼容 IE/Edge 浏览器
if ('msSaveOrOpenBlob' in (navigator as unknown as NavigatorWithMsSaveOrOpenBlob)) { if ('msSaveOrOpenBlob' in navigator) {
;(window.navigator as unknown as NavigatorWithMsSaveOrOpenBlob).msSaveOrOpenBlob(blob, tempName + fileType) return (navigator as unknown as NavigatorWithMsSaveOrOpenBlob).msSaveOrOpenBlob(blob, fileName)
} }
// 创建下载链接并触发下载
const blobUrl = window.URL.createObjectURL(blob) const blobUrl = window.URL.createObjectURL(blob)
const exportFile = document.createElement('a') const link = document.createElement('a')
exportFile.style.display = 'none' link.style.display = 'none'
exportFile.download = tempName link.download = fileName
exportFile.href = blobUrl link.href = blobUrl
document.body.appendChild(exportFile) document.body.appendChild(link)
exportFile.click() link.click()
// 去除下载对 url 的影响 // 清理资源
document.body.removeChild(exportFile) document.body.removeChild(link)
window.URL.revokeObjectURL(blobUrl) window.URL.revokeObjectURL(blobUrl)
} catch (error) { } catch (error) {
// console.log(error) const errorMsg = error instanceof Error ? error.message : '未知错误'
Message.error(`下载失败: ${errorMsg}`)
} }
} }