import * as FileApi from '@/api/mes/esopFile' import CryptoJS from 'crypto-js' import { UploadRawFile, UploadRequestOptions } from 'element-plus/es/components/upload/src/upload' import axios from 'axios' /** * 获得上传 URL */ export const getUploadUrl = (): string => { return import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + '/esop/file/create' } export const useUpload = () => { // 后端上传地址 const uploadUrl = getUploadUrl() // 是否使用前端直连上传 const isClientUpload = UPLOAD_TYPE.CLIENT === import.meta.env.VITE_UPLOAD_TYPE // 重写ElUpload上传方法 const httpRequest = async (options: UploadRequestOptions) => { // 模式一:前端上传 if (isClientUpload) { const fileName = await generateFileName(options.file) const presignedInfo = await FileApi.getFilePresignedUrl(fileName) return axios .put(presignedInfo.uploadUrl, options.file, { headers: { 'Content-Type': options.file.type } }) .then(() => { const fileVo = createFile(presignedInfo, fileName, options.file) return { code: 0, status: 0, data: { fileName: fileVo.path, fileUrl: fileVo.url }, msg: '' } }) } else { const fileVo = { file: options.file, code: options.data.params.code, name: options.data.params.name, type: options.data.params.type, classification: options.data.params.classification, status: options.data.params.status, } // 模式二:后端上传 // 重写 el-upload httpRequest 文件上传成功会走成功的钩子,失败走失败的钩子 return new Promise((resolve, reject) => { FileApi.updateFile(fileVo) .then((res) => { if (res.code === 0) { resolve(res) } else { reject(res) } }) .catch((res) => { reject(res) }) }) } } return { uploadUrl, httpRequest } } /** * 创建文件信息 * @param vo 文件预签名信息 * @param name 文件名称 * @param file 文件 */ function createFile(vo: FileApi.FilePresignedUrlRespVO, name: string, file: UploadRawFile) { const fileVo = { configId: vo.configId, url: vo.url, path: name, name: file.name, type: file.type, size: file.size } FileApi.createFile(fileVo) return fileVo } /** * 生成文件名称(使用算法SHA256) * @param file 要上传的文件 */ async function generateFileName(file: UploadRawFile) { // 读取文件内容 const data = await file.arrayBuffer() const wordArray = CryptoJS.lib.WordArray.create(data) // 计算SHA256 const sha256 = CryptoJS.SHA256(wordArray).toString() // 拼接后缀 const ext = file.name.substring(file.name.lastIndexOf('.')) return `${sha256}${ext}` } /** * 上传类型 */ enum UPLOAD_TYPE { // 客户端直接上传(只支持S3服务) CLIENT = 'client', // 客户端发送到后端上传 SERVER = 'server' }