文件下载
parent
fab8e1d9ad
commit
4b65fb8d5f
|
|
@ -1,9 +1,10 @@
|
|||
import {
|
||||
download,
|
||||
get,
|
||||
getFileUrl,
|
||||
} from '@/common/utils/http-util.ts'
|
||||
|
||||
import { saveFile } from '@/common/app'
|
||||
|
||||
interface PresignedUrl extends Record<string, string | undefined> {
|
||||
url?: string
|
||||
bucketName?: string
|
||||
|
|
@ -37,7 +38,7 @@ export default {
|
|||
obtainPresignedUrl(filename: string) {
|
||||
return get<PresignedUrl>('/oss/obtain_presigned_url', {filename})
|
||||
},
|
||||
download(filename: string, params?: any, defaultName: string = '下载的文件') {
|
||||
ossDownload(filename: string, params?: any) {
|
||||
let url = ''
|
||||
if (filename.startsWith('http') || filename.startsWith('https')) {
|
||||
url = filename
|
||||
|
|
@ -47,26 +48,7 @@ export default {
|
|||
} else {
|
||||
url = '/oss/download/' + filename
|
||||
}
|
||||
return download(url, params, defaultName)
|
||||
.then(res => {
|
||||
// 创建新的URL并指向File对象或者Blob对象的地址
|
||||
const blobURL = window.URL.createObjectURL(res.data.data)
|
||||
// 创建a标签,用于跳转至下载链接
|
||||
const tempLink = document.createElement('a')
|
||||
tempLink.style.display = 'none'
|
||||
tempLink.href = blobURL
|
||||
tempLink.setAttribute('download', decodeURI(res.data.filename))
|
||||
// 兼容:某些浏览器不支持HTML5的download属性
|
||||
if (typeof tempLink.download === 'undefined') {
|
||||
tempLink.setAttribute('target', '_blank')
|
||||
}
|
||||
// 挂载a标签
|
||||
document.body.appendChild(tempLink)
|
||||
tempLink.click()
|
||||
document.body.removeChild(tempLink)
|
||||
// 释放blob URL地址
|
||||
window.URL.revokeObjectURL(blobURL)
|
||||
})
|
||||
saveFile(get<{ content: Blob, filename: string }>(url, params, {responseType: 'arraybuffer'}))
|
||||
},
|
||||
fileUrl(filename?: string) {
|
||||
if (filename == null || filename.length <= 0) {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import Colls from '@/common/utils/colls.ts'
|
|||
import { useAppSettingStore } from '@/common/app/app-setting-store.ts'
|
||||
import { useAppUserStore } from '@/common/app/app-user-store.ts'
|
||||
import Utils from '@/common/utils'
|
||||
import type { R } from '@/common/utils/http-util.ts'
|
||||
|
||||
export const reloadUserInfo = () => {
|
||||
const appSettingStore = useAppSettingStore()
|
||||
|
|
@ -64,3 +65,27 @@ export function isAdmin() {
|
|||
const appUserStore = useAppUserStore()
|
||||
return appUserStore.roles != null && appUserStore.roles.includes('ROLE_ADMIN')
|
||||
}
|
||||
|
||||
export function saveFile(r: Promise<R<{ content: Blob, filename: string }>>, defaultName: string = '下载的文件') {
|
||||
return r.then(res => {
|
||||
const blobURL = window.URL.createObjectURL(res.data.content)
|
||||
const tempLink = document.createElement('a')
|
||||
try {
|
||||
tempLink.style.display = 'none'
|
||||
tempLink.href = blobURL
|
||||
tempLink.setAttribute('download', decodeURI(res.data.filename ?? defaultName))
|
||||
if (typeof tempLink.download === 'undefined') {
|
||||
tempLink.setAttribute('target', '_blank')
|
||||
}
|
||||
document.body.appendChild(tempLink)
|
||||
tempLink.click()
|
||||
return Promise.resolve()
|
||||
} catch (e) {
|
||||
console.log('下载失败', e)
|
||||
return Promise.reject()
|
||||
} finally {
|
||||
if (tempLink != null) document.body.removeChild(tempLink)
|
||||
if (blobURL != null) window.URL.revokeObjectURL(blobURL)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,9 +22,7 @@ export interface R<T = any> {
|
|||
headers?: AxiosRequestConfig['headers']
|
||||
}
|
||||
|
||||
type AxiosConfig = Pick<AxiosRequestConfig, 'headers' | 'params' | 'responseType'>
|
||||
// const closeUrls = closeUrl.split(',')
|
||||
// type ParamsSerializerType = Extract<AxiosRequestConfig['paramsSerializer'], any>;
|
||||
type AxiosConfig = Pick<AxiosRequestConfig, 'headers' | 'params' | 'responseType' | 'paramsSerializer'>
|
||||
|
||||
/**
|
||||
* Query 参数处理器
|
||||
|
|
@ -38,13 +36,11 @@ const paramsSerializer = (params: any) => {
|
|||
/**
|
||||
* 统一错误处理函数
|
||||
*/
|
||||
/* function errHandler(r?: R) {
|
||||
Toast.error(r?.message ?? '操作失败')
|
||||
} */
|
||||
const errHandler = Utils.throttle(500, (r?: AxiosResponse<R<any>, any>) => {
|
||||
console.log('异常处理', r)
|
||||
ElMessage.error(r?.data?.message ?? '服务器错误')
|
||||
ElMessage.error(r?.data?.message ?? (r?.data?.msg ?? '服务器错误'))
|
||||
})
|
||||
|
||||
/**
|
||||
* axios 实例
|
||||
*/
|
||||
|
|
@ -78,20 +74,23 @@ httpUtil.interceptors.request.use(
|
|||
*/
|
||||
httpUtil.interceptors.response.use(
|
||||
response => {
|
||||
// console.log('HTTP 请求结果', response.config.url, response)
|
||||
// vite 代理失败时 响应码为 200 响应内容为空
|
||||
if (response.config.responseType !== 'json') {
|
||||
return Promise.resolve(response)
|
||||
}
|
||||
if (response.data == null) {
|
||||
response.data = {code: 0, success: true, msg: '无响应内容', message: '无响应内容', data: null, headers: response.headers}
|
||||
response.data = {code: 5555, success: false, msg: '无响应内容', message: '无响应内容', data: null}
|
||||
} else if (response.config.responseType === 'arraybuffer') {
|
||||
const data = response.data as ArrayBufferView
|
||||
if (data.byteLength <= 0) {
|
||||
response.data = {code: 9999, success: false, msg: '文件获取失败', message: '文件获取失败', data: null}
|
||||
} else {
|
||||
const contentDisposition = response.headers['Content-Disposition'] ?? response.headers['content-disposition']
|
||||
const filename = getFileName(contentDisposition)
|
||||
// 将二进制流转为blob
|
||||
const blob = new Blob([ data ])
|
||||
response.data = {code: 0, success: true, msg: '成功', message: '文件获取成功', data: {content: blob, filename}}
|
||||
}
|
||||
}
|
||||
response.data.headers = response.headers
|
||||
if (response.data.code === 0) {
|
||||
return Promise.resolve(response)
|
||||
} else {
|
||||
return Promise.reject(response)
|
||||
}
|
||||
return response.data.code === 0 ? Promise.resolve(response) : Promise.reject(response)
|
||||
},
|
||||
error => {
|
||||
console.error('HTTP 请求失败', error)
|
||||
|
|
@ -114,17 +113,21 @@ httpUtil.interceptors.response.use(
|
|||
)
|
||||
|
||||
/**
|
||||
* GET 请求(JSON)
|
||||
* GET 请求
|
||||
*
|
||||
* @param url 请求地址
|
||||
* @param params Query 参数
|
||||
* @param config 配置
|
||||
* @param disposeErr 是否处理错误响应,默认-->true
|
||||
*/
|
||||
export function get<T = any>(url: string, params?: any, disposeErr: boolean = true) {
|
||||
/* if (closeUrls.includes(url)) {
|
||||
return Promise.reject({code: 0, success: true, msg: '', message: '', data: null} as R<T>)
|
||||
} */
|
||||
return httpUtil.get<R<T>>(url, {params, paramsSerializer, responseType: 'json'})
|
||||
export function get<T = any>(url: string, params?: any, config: AxiosConfig = {}, disposeErr: boolean = true) {
|
||||
if (config.responseType == null) {
|
||||
config.responseType = 'json'
|
||||
}
|
||||
config.params = params
|
||||
config.paramsSerializer = paramsSerializer
|
||||
|
||||
return httpUtil.get<R<T>>(url, config)
|
||||
.then(({data}) => data)
|
||||
.catch(res => {
|
||||
if (disposeErr) errHandler(res)
|
||||
|
|
@ -133,18 +136,21 @@ export function get<T = any>(url: string, params?: any, disposeErr: boolean = tr
|
|||
}
|
||||
|
||||
/**
|
||||
* POST 请求(JSON)
|
||||
* POST 请求
|
||||
*
|
||||
* @param url 请求地址
|
||||
* @param body Body 参数
|
||||
* @param params 参数
|
||||
* @param config 配置
|
||||
* @param disposeErr 是否处理错误响应,默认-->true
|
||||
*/
|
||||
export function post<T>(url: string, body?: any, params?: any, disposeErr: boolean = true) {
|
||||
/* if (closeUrls.includes(url)) {
|
||||
return Promise.reject({code: 0, success: true, msg: '', message: '', data: null} as R<T>)
|
||||
} */
|
||||
return httpUtil.post<R<T>>(url, body, {responseType: 'json', params})
|
||||
export function post<T>(url: string, body?: any, params?: any, config: AxiosConfig = {}, disposeErr: boolean = true) {
|
||||
if (config.responseType == null) {
|
||||
config.responseType = 'json'
|
||||
}
|
||||
config.params = params
|
||||
config.paramsSerializer = paramsSerializer
|
||||
return httpUtil.post<R<T>>(url, body, config)
|
||||
.then(({data}) => data)
|
||||
.catch(res => {
|
||||
if (disposeErr) errHandler(res)
|
||||
|
|
@ -222,26 +228,6 @@ function getFileName(contentDisposition: string) {
|
|||
return decodeURIComponent(fileNameWithoutQuotes)
|
||||
}
|
||||
|
||||
export function download(url: string, data?: any, params?: any, defaultName: string = '下载的文件', disposeErr: boolean = true) {
|
||||
return httpUtil.post(url, data, {params, paramsSerializer, responseType: 'arraybuffer'})
|
||||
.then(res => {
|
||||
const data = res.data
|
||||
if (!data || data.byteLength <= 0) {
|
||||
// 错误提示
|
||||
return Promise.reject({code: 9999, success: false, msg: '文件获取失败', message: '文件获取失败', data: null, headers: res.headers})
|
||||
}
|
||||
const contentDisposition = res.headers['Content-Disposition'] ?? res.headers['content-disposition']
|
||||
const filename = getFileName(contentDisposition) ?? defaultName
|
||||
// 将二进制流转为blob
|
||||
const blob = new Blob([ data ])
|
||||
return Promise.resolve({code: 0, success: true, msg: '成功', message: '文件获取成功', data: {data: blob, filename}, headers: res.headers})
|
||||
})
|
||||
.catch(res => {
|
||||
if (disposeErr) errHandler(res)
|
||||
return Promise.reject(res)
|
||||
})
|
||||
}
|
||||
|
||||
export function getFileUrl(path?: string) {
|
||||
if (path == null || path.length <= 0) {
|
||||
return ''
|
||||
|
|
@ -255,7 +241,6 @@ export default {
|
|||
post,
|
||||
postForm,
|
||||
postMltForm,
|
||||
download,
|
||||
getFileUrl,
|
||||
ins: httpUtil,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import {
|
||||
download,
|
||||
get,
|
||||
post,
|
||||
} from '@/common/utils/http-util.ts'
|
||||
import { saveFile } from '@/common/app'
|
||||
|
||||
export default {
|
||||
paging(data: TplTypes.SearchTplParam) {
|
||||
|
|
@ -23,30 +23,10 @@ export default {
|
|||
listAll(lang: string) {
|
||||
return get<TplTypes.SearchTplResult[]>('/tpl/list_all', {lang})
|
||||
},
|
||||
|
||||
preview(lang: string, tableName: string, data: Record<string, any>) {
|
||||
return post<TplTypes.CodeInfo>('/tpl/preview', data, {lang, tableName})
|
||||
},
|
||||
download(lang: string, tableName: string, data: Record<string, any>) {
|
||||
return download('/tpl/download', data, {lang, tableName})
|
||||
.then(res => {
|
||||
// 创建新的URL并指向File对象或者Blob对象的地址
|
||||
const blobURL = window.URL.createObjectURL(res.data.data)
|
||||
// 创建a标签,用于跳转至下载链接
|
||||
const tempLink = document.createElement('a')
|
||||
tempLink.style.display = 'none'
|
||||
tempLink.href = blobURL
|
||||
tempLink.setAttribute('download', decodeURI(res.data.filename))
|
||||
// 兼容:某些浏览器不支持HTML5的download属性
|
||||
if (typeof tempLink.download === 'undefined') {
|
||||
tempLink.setAttribute('target', '_blank')
|
||||
}
|
||||
// 挂载a标签
|
||||
document.body.appendChild(tempLink)
|
||||
tempLink.click()
|
||||
document.body.removeChild(tempLink)
|
||||
// 释放blob URL地址
|
||||
window.URL.revokeObjectURL(blobURL)
|
||||
})
|
||||
return saveFile(post('/tpl/download', data, {lang, tableName}, {responseType: 'arraybuffer'}))
|
||||
},
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue