- UploadConfigService: PUT预签名URL改为生成POST Object的policy+signature - IUploadConfigService: PresignedUploadInfo增加Key/Policy/SecretId/KeyTime/Signature字段 - uniapp/upload.js: uni.uploadFile改为POST multipart/form-data + formData传签名参数 - 后台管理端上传不受影响,仍走独立的TencentCosProvider PUT预签名链路
83 lines
2.5 KiB
JavaScript
83 lines
2.5 KiB
JavaScript
/**
|
|
* COS直传工具
|
|
* 通过POST Object方式将文件直传到腾讯云COS
|
|
* 参考: https://cloud.tencent.com/document/product/436/14690
|
|
*/
|
|
|
|
import { getPresignedUploadUrl } from '@/api/user.js'
|
|
|
|
/**
|
|
* 选择图片并上传到COS
|
|
* @param {Object} [options] - 选项
|
|
* @param {number} [options.count=1] - 选择数量
|
|
* @param {string[]} [options.sourceType] - 来源类型
|
|
* @returns {Promise<string>} 上传后的文件URL
|
|
*/
|
|
export async function chooseAndUploadImage(options = {}) {
|
|
const { count = 1, sourceType = ['album', 'camera'] } = options
|
|
|
|
// 1. 选择图片
|
|
const chooseRes = await new Promise((resolve, reject) => {
|
|
uni.chooseImage({
|
|
count,
|
|
sizeType: ['compressed'],
|
|
sourceType,
|
|
success: resolve,
|
|
fail: (err) => {
|
|
if (err.errMsg && err.errMsg.includes('cancel')) {
|
|
reject(new Error('用户取消选择'))
|
|
} else {
|
|
reject(new Error('选择图片失败'))
|
|
}
|
|
}
|
|
})
|
|
})
|
|
|
|
const tempFilePath = chooseRes.tempFilePaths[0]
|
|
const fileName = tempFilePath.split('/').pop() || 'image.png'
|
|
|
|
// 判断文件类型
|
|
const ext = fileName.split('.').pop()?.toLowerCase() || 'png'
|
|
const mimeMap = { jpg: 'image/jpeg', jpeg: 'image/jpeg', png: 'image/png', gif: 'image/gif', webp: 'image/webp' }
|
|
const contentType = mimeMap[ext] || 'image/png'
|
|
|
|
// 2. 获取POST Object签名信息
|
|
const presignedRes = await getPresignedUploadUrl(fileName, contentType)
|
|
if (!presignedRes || presignedRes.code !== 0 || !presignedRes.data) {
|
|
throw new Error(presignedRes?.message || '获取上传地址失败')
|
|
}
|
|
|
|
const { uploadUrl, fileUrl, key, policy, secretId, keyTime, signature } = presignedRes.data
|
|
|
|
// 3. POST Object方式直传COS
|
|
await new Promise((resolve, reject) => {
|
|
uni.uploadFile({
|
|
url: uploadUrl,
|
|
filePath: tempFilePath,
|
|
name: 'file',
|
|
formData: {
|
|
'key': key,
|
|
'policy': policy,
|
|
'q-sign-algorithm': 'sha1',
|
|
'q-ak': secretId,
|
|
'q-key-time': keyTime,
|
|
'q-sign-time': keyTime,
|
|
'q-signature': signature
|
|
},
|
|
success: (res) => {
|
|
// COS POST Object成功返回 200 或 204
|
|
if (res.statusCode >= 200 && res.statusCode < 300) {
|
|
resolve(res)
|
|
} else {
|
|
console.error('COS上传失败:', res.statusCode, res.data)
|
|
reject(new Error(`上传失败,状态码: ${res.statusCode}`))
|
|
}
|
|
},
|
|
fail: (err) => reject(new Error(err.errMsg || '上传失败'))
|
|
})
|
|
})
|
|
|
|
// 4. 返回文件访问URL
|
|
return fileUrl
|
|
}
|