This commit is contained in:
oneao committed 2026-03-28 17:22:49 +08:00
1 parent ce466130c0
commit 9c026f00ad
36 files changed
+2230 -1036

No files matched your search

@@ -1,5 +1,5 @@
import { toast } from 'sard-uniapp'
import { getaliyunkeyApi } from '@/request/api'
import { getOssKey } from './oss'
import { isApp, isH5, isMpWeixin } from './platform'
const aliyunBucket = import.meta.env.VITE_ALIYUN_BUCKET
@@ -115,70 +115,12 @@ export function formatFileSize(size: number): string {
else return `${(size / (1024 * 1024 * 1024)).toFixed(2)} GB`
}
export interface AliyunUploadResult {
url: string // 上传后的完整 URL
}
/**
* 上传文件到阿里云 OSS
* @param filePath 本地文件路径
* @param fileName 文件名
* @param fileType 文件类型,可选:image/video/file
* @returns Promise<AliyunUploadResult>
* 上传文件到阿里云 OSS(优化版)
*/
export async function uploadFileToAliyun(
filePath: string,
fileName: string,
fileType: any,
): Promise<AliyunUploadResult> {
// 获取 OSS 临时上传凭证
const keyRes = await getaliyunkeyApi({
bucketName: aliyunBucket,
})
const { accessid, callback, dir, host, policy, signature } = keyRes.data
// 构建文件在 OSS 的存储路径
const fileExtension = fileName.split('.').pop()?.toLowerCase() || 'tmp'
const timestamp = Date.now()
const random = Math.floor(Math.random() * 1000)
const key = `${dir}${timestamp + random}.${fileExtension}`
const formData: Record<string, any> = {
key,
OSSAccessKeyId: accessid,
policy,
signature,
success_action_status: '200',
name: fileName,
}
if (callback)
formData.callback = callback
// 使用 Promise 包裹 uni.uploadFile
return new Promise<AliyunUploadResult>((resolve, reject) => {
uni.uploadFile({
url: host,
filePath,
name: 'file',
fileName,
fileType,
formData,
success: (res) => {
if (res.statusCode === 200) {
resolve({
url: `${host}/${key}`,
})
}
else {
reject(new Error(`上传失败,状态码: ${res.statusCode}`))
}
},
fail: (err) => {
reject(err)
},
})
})
}
/** =================== 工具函数 =================== */
/** 获取文件名:从 URL 提取最后一段 */
@@ -0,0 +1,116 @@
// utils/ossManager.ts
import { getAliyunkeyApi } from '@/request/api'
const aliyunBucket = import.meta.env.VITE_ALIYUN_BUCKET
interface OssKey {
accessid: string
callback?: string
dir: string
host: string
policy: string
signature: string
expire: number
}
interface OssUpdateResult {
url: string // 上传后的完整 URL
}
// ✅ 模块级缓存(天然单例)
let ossKeyCache: OssKey | null = null
let ossKeyPromise: Promise<OssKey> | null = null
/**
* 获取 OSS Key(缓存 + 并发锁)
*/
export async function getOssKey(): Promise<OssKey> {
const now = Math.floor(Date.now() / 1000)
const SAFE_GAP = 10 // 提前10秒过期
// ✅ 命中缓存
if (ossKeyCache && ossKeyCache.expire - SAFE_GAP > now) {
console.log('===命中缓存===')
return ossKeyCache
}
// ✅ 并发锁
if (ossKeyPromise) {
return ossKeyPromise
}
// ✅ 请求
ossKeyPromise = getAliyunkeyApi({
bucketName: aliyunBucket,
})
.then((res) => {
console.log('===重新请求===')
const data = res.data
ossKeyCache = {
accessid: data.accessid,
callback: data.callback,
dir: data.dir,
host: data.host,
policy: data.policy,
signature: data.signature,
expire: Number(data.expire),
}
return ossKeyCache
})
.finally(() => {
ossKeyPromise = null
})
return ossKeyPromise
}
export async function uploadToOss(
filePath: string,
fileName: string,
fileType?: 'image' | 'video' | 'file',
): Promise<OssUpdateResult> {
// ✅ 使用缓存后的 key
const { accessid, callback, dir, host, policy, signature } = await getOssKey()
// 生成文件路径
const ext = fileName.split('.').pop()?.toLowerCase() || 'tmp'
const key = `${dir}${Date.now()}_${Math.floor(Math.random() * 1000)}.${ext}`
const formData: Record<string, any> = {
key,
OSSAccessKeyId: accessid,
policy,
signature,
success_action_status: '200',
name: fileName,
}
if (callback) {
formData.callback = callback
}
return new Promise<OssUpdateResult>((resolve, reject) => {
uni.uploadFile({
url: host,
filePath,
name: 'file',
fileName,
fileType: 'image',
formData,
success: (res) => {
if (res.statusCode === 200) {
resolve({
url: `${host}/${key}`,
})
}
else {
reject(new Error(`上传失败,状态码: ${res.statusCode}`))
}
},
fail: reject,
})
})
}
@@ -1,9 +1,3 @@
/*
* @Author: 菲鸽
* @Date: 2024-03-28 19:13:55
* @Last Modified by: 菲鸽
* @Last Modified time: 2024-03-28 19:24:55
*/
export const platform = __UNI_PLATFORM__
export const isH5 = __UNI_PLATFORM__ === 'h5'
export const isApp = __UNI_PLATFORM__ === 'app'
@@ -13,6 +7,11 @@ export const isMpAplipay = __UNI_PLATFORM__.startsWith('mp-alipay')
export const isMpToutiao = __UNI_PLATFORM__.startsWith('mp-toutiao')
export const isHarmony = __UNI_PLATFORM__.startsWith('app-harmony')
function isInWeChat() {
const ua = navigator.userAgent.toLowerCase()
return ua.includes('micromessenger')
}
const PLATFORM = {
platform,
isH5,
@@ -22,5 +21,6 @@ const PLATFORM = {
isMpAplipay,
isMpToutiao,
isHarmony,
isInWeChat
}
export default PLATFORM