94 lines
2.8 KiB
JavaScript
94 lines
2.8 KiB
JavaScript
import { post } from './api'
|
|
|
|
/**
|
|
* 从后端获取 COS 预签名上传 URL
|
|
* @param {number} count - 文件数量
|
|
* @param {string} ext - 文件扩展名
|
|
* @returns {Promise<Array<{cosKey, presignUrl, accessUrl}>>}
|
|
*/
|
|
export async function getPresignUrls(count, ext = '.jpg') {
|
|
const res = await post('/business/CosUpload/presignUrl', { count, ext })
|
|
if (res.code !== 200) {
|
|
throw new Error(res.msg || '获取上传地址失败')
|
|
}
|
|
return res.data
|
|
}
|
|
|
|
/**
|
|
* 通过预签名 URL 直传文件到 COS
|
|
* @param {string} presignUrl - PUT 预签名 URL
|
|
* @param {string} filePath - 本地文件路径
|
|
* @returns {Promise<void>}
|
|
*/
|
|
export function uploadToCos(presignUrl, filePath) {
|
|
return new Promise((resolve, reject) => {
|
|
// #ifdef H5
|
|
_uploadH5(presignUrl, filePath).then(resolve).catch(reject)
|
|
// #endif
|
|
// #ifdef APP-PLUS
|
|
_uploadApp(presignUrl, filePath).then(resolve).catch(reject)
|
|
// #endif
|
|
})
|
|
}
|
|
|
|
// #ifdef H5
|
|
async function _uploadH5(presignUrl, filePath) {
|
|
// H5 端 filePath 可能是 base64 或 blob URL
|
|
let blob
|
|
if (filePath.startsWith('data:')) {
|
|
const resp = await fetch(filePath)
|
|
blob = await resp.blob()
|
|
} else {
|
|
const resp = await fetch(filePath)
|
|
blob = await resp.blob()
|
|
}
|
|
const res = await fetch(presignUrl, {
|
|
method: 'PUT',
|
|
headers: { 'Content-Type': 'image/jpeg' },
|
|
body: blob
|
|
})
|
|
if (!res.ok) {
|
|
throw new Error(`COS上传失败: ${res.status}`)
|
|
}
|
|
}
|
|
// #endif
|
|
|
|
// #ifdef APP-PLUS
|
|
function _uploadApp(presignUrl, filePath) {
|
|
return new Promise((resolve, reject) => {
|
|
plus.io.resolveLocalFileSystemURL(filePath, (entry) => {
|
|
entry.file((file) => {
|
|
const reader = new plus.io.FileReader()
|
|
reader.onloadend = (e) => {
|
|
const base64 = e.target.result
|
|
// 将 base64 转为 ArrayBuffer
|
|
const binary = atob(base64.split(',')[1])
|
|
const len = binary.length
|
|
const bytes = new Uint8Array(len)
|
|
for (let i = 0; i < len; i++) {
|
|
bytes[i] = binary.charCodeAt(i)
|
|
}
|
|
// 使用 XMLHttpRequest 发送 PUT
|
|
const xhr = new XMLHttpRequest()
|
|
xhr.open('PUT', presignUrl, true)
|
|
xhr.setRequestHeader('Content-Type', 'image/jpeg')
|
|
xhr.onload = () => {
|
|
if (xhr.status >= 200 && xhr.status < 300) {
|
|
resolve()
|
|
} else {
|
|
reject(new Error(`COS上传失败: ${xhr.status}`))
|
|
}
|
|
}
|
|
xhr.onerror = () => reject(new Error('COS上传网络错误'))
|
|
xhr.send(bytes.buffer)
|
|
}
|
|
reader.onerror = () => reject(new Error('读取文件失败'))
|
|
reader.readAsDataURL(file)
|
|
})
|
|
}, (err) => {
|
|
reject(new Error('解析文件路径失败: ' + JSON.stringify(err)))
|
|
})
|
|
})
|
|
}
|
|
// #endif
|