feat: 添加 S3 文件上传功能,更新 '@capp/eden' 依赖至 0.0.11,优化实名认证表单逻辑
This commit is contained in:
77
src/utils/aws/s3.ts
Normal file
77
src/utils/aws/s3.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
import type { TreatyBody } from "@/api/types";
|
||||
import { client, safeClient } from "@/api";
|
||||
|
||||
interface UploadOptions {
|
||||
fetchOptions: UploadFetchOptions;
|
||||
onProgress?: (progress: number) => void;
|
||||
signal?: AbortSignal;
|
||||
}
|
||||
|
||||
export type UploadFetchOptions = TreatyBody<typeof client.api.file_storage.upload_url.post>;
|
||||
|
||||
export async function uploadToS3(file: File, options: UploadOptions): Promise<string> {
|
||||
const { onProgress, signal, fetchOptions } = options;
|
||||
|
||||
// 1. 获取预签名 URL
|
||||
const { data, error } = await safeClient(client.api.file_storage.upload_url.post({
|
||||
...fetchOptions,
|
||||
}));
|
||||
|
||||
if (error.value || !data.value) {
|
||||
throw new Error("获取上传 URL 失败");
|
||||
}
|
||||
const { fileId, uploadUrl, method, headers } = toRefs(data.value);
|
||||
|
||||
// 2. 上传文件到 S3
|
||||
return new Promise((resolve, reject) => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
|
||||
// 监听上传进度
|
||||
xhr.upload.addEventListener("progress", (e: ProgressEvent) => {
|
||||
if (e.lengthComputable && onProgress) {
|
||||
const progress = Math.round((e.loaded / e.total) * 100);
|
||||
onProgress(progress);
|
||||
}
|
||||
});
|
||||
|
||||
// 上传成功
|
||||
xhr.addEventListener("load", () => {
|
||||
if (xhr.status >= 200 && xhr.status < 300) {
|
||||
resolve(fileId.value);
|
||||
}
|
||||
else {
|
||||
reject(new Error(`上传失败: ${xhr.status} ${xhr.statusText}`));
|
||||
}
|
||||
});
|
||||
|
||||
// 网络错误
|
||||
xhr.addEventListener("error", () => {
|
||||
reject(new Error("网络错误,上传失败"));
|
||||
});
|
||||
|
||||
// 上传取消
|
||||
xhr.addEventListener("abort", () => {
|
||||
reject(new Error("上传已取消"));
|
||||
});
|
||||
|
||||
// 超时
|
||||
xhr.addEventListener("timeout", () => {
|
||||
reject(new Error("上传超时"));
|
||||
});
|
||||
|
||||
// 支持外部取消
|
||||
if (signal) {
|
||||
signal.addEventListener("abort", () => {
|
||||
xhr.abort();
|
||||
});
|
||||
}
|
||||
|
||||
// 开始上传
|
||||
xhr.open(method.value, uploadUrl.value, true);
|
||||
for (const [key, value] of Object.entries(headers.value)) {
|
||||
xhr.setRequestHeader(key, value);
|
||||
}
|
||||
xhr.timeout = 300000; // 5分钟超时
|
||||
xhr.send(file);
|
||||
});
|
||||
}
|
||||
1
src/utils/index.ts
Normal file
1
src/utils/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from "./aws/s3";
|
||||
Reference in New Issue
Block a user