feat: 支持批量上传关卡
This commit is contained in:
81
lib/cos-client.ts
Normal file
81
lib/cos-client.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
import COS from 'cos-js-sdk-v5'
|
||||
import { apiFetch } from '@/lib/api'
|
||||
|
||||
interface TempKeyResponse {
|
||||
credentials: {
|
||||
tmpSecretId: string
|
||||
tmpSecretKey: string
|
||||
sessionToken: string
|
||||
}
|
||||
startTime: number
|
||||
expiredTime: number
|
||||
bucket: string
|
||||
region: string
|
||||
}
|
||||
|
||||
let cachedKey: TempKeyResponse | null = null
|
||||
|
||||
async function getTempKey(forceRefresh = false): Promise<TempKeyResponse> {
|
||||
const now = Math.floor(Date.now() / 1000)
|
||||
// 提前 60 秒失效,避免边界问题
|
||||
if (!forceRefresh && cachedKey && cachedKey.expiredTime - 60 > now) {
|
||||
return cachedKey
|
||||
}
|
||||
const res = await apiFetch('/api/cos/temp-key')
|
||||
if (!res.ok) {
|
||||
throw new Error('获取上传凭证失败')
|
||||
}
|
||||
const data = (await res.json()) as TempKeyResponse
|
||||
cachedKey = data
|
||||
return data
|
||||
}
|
||||
|
||||
function buildCosClient(key: TempKeyResponse): COS {
|
||||
return new COS({
|
||||
getAuthorization: (_options, callback) => {
|
||||
callback({
|
||||
TmpSecretId: key.credentials.tmpSecretId,
|
||||
TmpSecretKey: key.credentials.tmpSecretKey,
|
||||
SecurityToken: key.credentials.sessionToken,
|
||||
StartTime: key.startTime,
|
||||
ExpiredTime: key.expiredTime,
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
function randomFilename(originalName: string): string {
|
||||
const ext = originalName.split('.').pop() || 'jpg'
|
||||
const timestamp = Date.now()
|
||||
const randomStr = Math.random().toString(36).substring(2, 8)
|
||||
return `mini_game/images/${timestamp}_${randomStr}.${ext}`
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传单个文件到腾讯云 COS,返回可访问的 URL。
|
||||
*/
|
||||
export async function uploadToCos(file: File | Blob, originalName?: string): Promise<string> {
|
||||
const name = originalName || (file as File).name || 'upload.jpg'
|
||||
const key = await getTempKey()
|
||||
const cos = buildCosClient(key)
|
||||
const filename = randomFilename(name)
|
||||
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
cos.putObject(
|
||||
{
|
||||
Bucket: key.bucket,
|
||||
Region: key.region,
|
||||
Key: filename,
|
||||
Body: file as File,
|
||||
},
|
||||
(err) => {
|
||||
if (err) {
|
||||
reject(new Error(err.message || '上传失败'))
|
||||
return
|
||||
}
|
||||
const url = `https://${key.bucket}.cos.${key.region}.myqcloud.com/${filename}`
|
||||
resolve(url)
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user