提交 | 用户 | 时间
|
820397
|
1 |
import * as FileApi from '@/api/infra/file' |
H |
2 |
import CryptoJS from 'crypto-js' |
|
3 |
import { UploadRawFile, UploadRequestOptions } from 'element-plus/es/components/upload/src/upload' |
|
4 |
import axios from 'axios' |
|
5 |
|
221c1c
|
6 |
/** |
H |
7 |
* 获得上传 URL |
|
8 |
*/ |
|
9 |
export const getUploadUrl = (): string => { |
|
10 |
return import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + '/infra/file/upload' |
|
11 |
} |
|
12 |
|
820397
|
13 |
export const useUpload = () => { |
H |
14 |
// 后端上传地址 |
221c1c
|
15 |
const uploadUrl = getUploadUrl() |
820397
|
16 |
// 是否使用前端直连上传 |
H |
17 |
const isClientUpload = UPLOAD_TYPE.CLIENT === import.meta.env.VITE_UPLOAD_TYPE |
|
18 |
// 重写ElUpload上传方法 |
|
19 |
const httpRequest = async (options: UploadRequestOptions) => { |
|
20 |
// 模式一:前端上传 |
|
21 |
if (isClientUpload) { |
|
22 |
// 1.1 生成文件名称 |
|
23 |
const fileName = await generateFileName(options.file) |
|
24 |
// 1.2 获取文件预签名地址 |
|
25 |
const presignedInfo = await FileApi.getFilePresignedUrl(fileName) |
|
26 |
// 1.3 上传文件(不能使用 ElUpload 的 ajaxUpload 方法的原因:其使用的是 FormData 上传,Minio 不支持) |
221c1c
|
27 |
return axios |
H |
28 |
.put(presignedInfo.uploadUrl, options.file, { |
|
29 |
headers: { |
|
30 |
'Content-Type': options.file.type |
|
31 |
} |
|
32 |
}) |
|
33 |
.then(() => { |
|
34 |
// 1.4. 记录文件信息到后端(异步) |
|
35 |
createFile(presignedInfo, fileName, options.file) |
|
36 |
// 通知成功,数据格式保持与后端上传的返回结果一致 |
|
37 |
return { data: presignedInfo.url } |
|
38 |
}) |
820397
|
39 |
} else { |
H |
40 |
// 模式二:后端上传 |
|
41 |
// 重写 el-upload httpRequest 文件上传成功会走成功的钩子,失败走失败的钩子 |
|
42 |
return new Promise((resolve, reject) => { |
|
43 |
FileApi.updateFile({ file: options.file }) |
|
44 |
.then((res) => { |
|
45 |
if (res.code === 0) { |
|
46 |
resolve(res) |
|
47 |
} else { |
|
48 |
reject(res) |
|
49 |
} |
|
50 |
}) |
|
51 |
.catch((res) => { |
|
52 |
reject(res) |
|
53 |
}) |
|
54 |
}) |
|
55 |
} |
|
56 |
} |
|
57 |
|
|
58 |
return { |
|
59 |
uploadUrl, |
|
60 |
httpRequest |
|
61 |
} |
|
62 |
} |
|
63 |
|
|
64 |
/** |
|
65 |
* 创建文件信息 |
|
66 |
* @param vo 文件预签名信息 |
|
67 |
* @param name 文件名称 |
|
68 |
* @param file 文件 |
|
69 |
*/ |
|
70 |
function createFile(vo: FileApi.FilePresignedUrlRespVO, name: string, file: UploadRawFile) { |
|
71 |
const fileVo = { |
|
72 |
configId: vo.configId, |
|
73 |
url: vo.url, |
|
74 |
path: name, |
|
75 |
name: file.name, |
|
76 |
type: file.type, |
|
77 |
size: file.size |
|
78 |
} |
|
79 |
FileApi.createFile(fileVo) |
|
80 |
return fileVo |
|
81 |
} |
|
82 |
|
|
83 |
/** |
|
84 |
* 生成文件名称(使用算法SHA256) |
|
85 |
* @param file 要上传的文件 |
|
86 |
*/ |
|
87 |
async function generateFileName(file: UploadRawFile) { |
|
88 |
// 读取文件内容 |
|
89 |
const data = await file.arrayBuffer() |
|
90 |
const wordArray = CryptoJS.lib.WordArray.create(data) |
|
91 |
// 计算SHA256 |
|
92 |
const sha256 = CryptoJS.SHA256(wordArray).toString() |
|
93 |
// 拼接后缀 |
|
94 |
const ext = file.name.substring(file.name.lastIndexOf('.')) |
|
95 |
return `${sha256}${ext}` |
|
96 |
} |
|
97 |
|
|
98 |
/** |
|
99 |
* 上传类型 |
|
100 |
*/ |
|
101 |
enum UPLOAD_TYPE { |
|
102 |
// 客户端直接上传(只支持S3服务) |
|
103 |
CLIENT = 'client', |
|
104 |
// 客户端发送到后端上传 |
|
105 |
SERVER = 'server' |
|
106 |
} |