import type OSS from 'ali-oss' import { getSTSToken, getOssSignatureUrl, checkOssSignatureUrlIsExist, } from '@apis/oss' import type { STSTokenResponse, UploadParams, UploadResult } from '../type' import { OSSBucketType } from '../type' import { StorageAdapter } from './base' // 常量定义 const OSS_REGION = 'oss-cn-hangzhou' export class OSSClient extends StorageAdapter { private static instance: OSSClient // 获取默认实例键值 protected getDefaultInstanceKey(): string { return 'bty-oss-token' } // 获取提供商前缀 protected getProviderPrefix(): string { return 'custom-oss' } // 默认获取STS Token的方法 protected async defaultGetSTSToken(): Promise { return getSTSToken() } // 获取默认OSSClient单例 public static getInstance(): OSSClient { if (!OSSClient.instance) { OSSClient.instance = new OSSClient() } return OSSClient.instance } // 创建自定义OSSClient实例 public static createCustomInstance( getSTSTokenFn: () => Promise, ): OSSClient { return new OSSClient(getSTSTokenFn) } // 刷新OSS客户端 protected async refreshClient(): Promise { const token = await this.getSTSToken() const aliOssModule: any = await import('ali-oss') const OSSSdk: typeof OSS = aliOssModule.default || (aliOssModule as any) this.client = new OSSSdk({ region: token.region || OSS_REGION, accessKeyId: token.access_key_id, accessKeySecret: token.access_key_secret, stsToken: token.security_token, secure: true, ...(Reflect.has(token, 'secure') ? { secure: token.secure } : {}), }) this.bucketMap = { [OSSBucketType.PRIVATE]: token.data_bucket, [OSSBucketType.PUBLIC]: token.resource_bucket, } as Record } // 上传文件 public async upload(params: UploadParams): Promise { try { const client = await this.getClient() const bucketName = params.custom_bucket || this.getBucketName(params.bucketType || OSSBucketType.PRIVATE) client!.useBucket(bucketName) const result = await client.put( params.filePath, params.file, params.options || {}, ) const url = (result.res as any)?.requestUrls?.[0]?.split('?')?.[0] return { url, result } } catch (error) { console.error('File upload failed:', error) throw new Error(`File upload failed: ${(error as Error).message}`) } } public async multipartUpload(params: UploadParams): Promise { try { const client = await this.getClient() const bucketName = params.custom_bucket || this.getBucketName(params.bucketType || OSSBucketType.PRIVATE) client!.useBucket(bucketName) const result = await client.multipartUpload( params.filePath, params.file, params.options || {}, ) const url = (result.res as any)?.requestUrls?.[0]?.split('?')?.[0] return { url, result } } catch (error) { console.error('File upload failed:', error) throw new Error(`File upload failed: ${(error as Error).message}`) } } public async getOssSignatureUrl(key: string, params?: Record) { return getOssSignatureUrl(key, params) } public async checkOssSignatureUrlIsExist(url: string) { return checkOssSignatureUrlIsExist(url) } }