| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- import OSS from "ali-oss";
- import { http } from "@/utils/http";
- interface OssCredential {
- accessKeyId: string;
- accessKeySecret: string;
- securityToken: string;
- expiration: string;
- host: string;
- dir: string;
- }
- export interface UploadResult {
- url: string;
- objectKey: string;
- fileName: string;
- fileSize: number;
- fileExtension: string;
- }
- let cachedCredential: OssCredential | null = null;
- let credentialExpireTime = 0;
- /**
- * 获取 OSS 上传凭证(带缓存,过期前60秒自动刷新)
- */
- async function getOssCredential(dir: string): Promise<OssCredential> {
- const now = Date.now();
- if (cachedCredential && credentialExpireTime - now > 60000) {
- return cachedCredential;
- }
- const res = await http.request<{
- code: number;
- message: string;
- data: OssCredential;
- }>("get", "/oss/upload-credential", { params: { dir } });
- if (res.code !== 200) {
- throw new Error(res.message || "获取上传凭证失败");
- }
- cachedCredential = res.data;
- credentialExpireTime = new Date(res.data.expiration).getTime();
- return cachedCredential;
- }
- /**
- * 前端直传文件到 OSS
- *
- * @param file 待上传文件
- * @param dir 上传目录(如 "shop-archive/contract")
- * @param onProgress 上传进度回调 (percent: number) => void
- * @returns 上传结果(URL、objectKey等)
- */
- export async function uploadToOss(
- file: File,
- dir: string = "shop-archive",
- onProgress?: (percent: number) => void
- ): Promise<UploadResult> {
- const credential = await getOssCredential(dir);
- // 从 host 中提取 region 和 bucket
- const hostMatch = credential.host.match(
- /\/\/(.+?)\.(oss-.+?)\.aliyuncs\.com/
- );
- const bucket = hostMatch?.[1] || "";
- const region = hostMatch?.[2] || "oss-cn-hangzhou";
- const client = new OSS({
- region,
- accessKeyId: credential.accessKeyId,
- accessKeySecret: credential.accessKeySecret,
- stsToken: credential.securityToken,
- bucket,
- endpoint: credential.host
- });
- // 生成 objectKey:dir/yyyyMMdd/uuid.ext
- const ext = file.name.includes(".")
- ? file.name.substring(file.name.lastIndexOf("."))
- : "";
- const dateStr = new Date()
- .toISOString()
- .slice(0, 10)
- .replace(/-/g, "");
- const uuid = Math.random().toString(36).substring(2, 15) + Date.now().toString(36);
- const objectKey = `${credential.dir}${dateStr}/${uuid}${ext}`;
- await client.put(objectKey, file, {
- progress: (p: number) => onProgress?.(Math.round(p * 100))
- });
- // 拼接完整访问URL
- const url = `${credential.host.replace(/\/$/, "")}/${objectKey}`;
- return {
- url,
- objectKey,
- fileName: file.name,
- fileSize: file.size,
- fileExtension: ext.replace(".", "")
- };
- }
|