| | |
| | | import type { Ref } from 'vue'; |
| | | |
| | | import type { AxiosProgressEvent, InfraFileApi } from '#/api/infra/file'; |
| | | import type { AxiosProgressEvent } from '#/api/infra/file'; |
| | | |
| | | import { computed, unref } from 'vue'; |
| | | |
| | | import { useAppConfig } from '@vben/hooks'; |
| | | import { $t } from '@vben/locales'; |
| | | |
| | | import { createFile, getFilePresignedUrl, uploadFile } from '#/api/infra/file'; |
| | | import { baseRequestClient } from '#/api/request'; |
| | | import { requestClient } from '#/api/request'; |
| | | |
| | | const { apiURL } = useAppConfig(import.meta.env, import.meta.env.PROD); |
| | | |
| | |
| | | // 是否使用前端直连上传 |
| | | const isClientUpload = |
| | | UPLOAD_TYPE.CLIENT === import.meta.env.VITE_UPLOAD_TYPE; |
| | | // 重写ElUpload上传方法 |
| | | // 重写上传方法,统一走 system 模块 Storage API |
| | | async function httpRequest( |
| | | file: File, |
| | | onUploadProgress?: AxiosProgressEvent, |
| | | ) { |
| | | // 模式一:前端上传 |
| | | if (isClientUpload) { |
| | | // 1.1 生成文件名称 |
| | | const fileName = await generateFileName(file); |
| | | // 1.2 获取文件预签名地址 |
| | | const presignedInfo = await getFilePresignedUrl(fileName, directory); |
| | | // 1.3 上传文件 |
| | | return baseRequestClient |
| | | .put(presignedInfo.uploadUrl, file, { |
| | | headers: { |
| | | 'Content-Type': file.type, |
| | | }, |
| | | }) |
| | | .then(() => { |
| | | // 1.4. 记录文件信息到后端(异步) |
| | | createFile0(presignedInfo, file); |
| | | // 通知成功,数据格式保持与后端上传的返回结果一致 |
| | | return { url: presignedInfo.url }; |
| | | const formData = new FormData(); |
| | | formData.append('files', file); |
| | | const blobs = await requestClient.post('/system/storage-blob/upload', formData, { |
| | | onUploadProgress, |
| | | }); |
| | | } else { |
| | | // 模式二:后端上传 |
| | | return uploadFile({ file, directory }, onUploadProgress); |
| | | } |
| | | const blob = Array.isArray(blobs) ? blobs[0] : blobs; |
| | | return blob ? { url: blob.url || blob.previewURL, name: blob.name, id: blob.id } : {}; |
| | | } |
| | | |
| | | return { |
| | |
| | | } |
| | | |
| | | /** |
| | | * 获得上传 URL |
| | | * 获得上传 URL(兼容旧版,实际调用走 httpRequest) |
| | | */ |
| | | export function getUploadUrl(): string { |
| | | return `${apiURL}/infra/file/upload`; |
| | | } |
| | | |
| | | /** |
| | | * 创建文件信息 |
| | | * |
| | | * @param vo 文件预签名信息 |
| | | * @param file 文件 |
| | | */ |
| | | function createFile0( |
| | | vo: InfraFileApi.FilePresignedUrlRespVO, |
| | | file: File, |
| | | ): InfraFileApi.File { |
| | | const fileVO = { |
| | | configId: vo.configId, |
| | | url: vo.url, |
| | | path: vo.path, |
| | | name: file.name, |
| | | type: file.type, |
| | | size: file.size, |
| | | }; |
| | | createFile(fileVO); |
| | | return fileVO; |
| | | } |
| | | |
| | | /** |
| | | * 生成文件名称(使用算法SHA256) |
| | | * |
| | | * @param file 要上传的文件 |
| | | */ |
| | | async function generateFileName(file: File) { |
| | | // // 读取文件内容 |
| | | // const data = await file.arrayBuffer(); |
| | | // const wordArray = CryptoJS.lib.WordArray.create(data); |
| | | // // 计算SHA256 |
| | | // const sha256 = CryptoJS.SHA256(wordArray).toString(); |
| | | // // 拼接后缀 |
| | | // const ext = file.name.slice(Math.max(0, file.name.lastIndexOf('.'))); |
| | | // return `${sha256}${ext}`; |
| | | return file.name; |
| | | return `${apiURL}/system/storage-blob/upload`; |
| | | } |