chuangte_bike_newxcx/common/qiniuUploadUtil.js
2026-05-25 17:13:15 +08:00

203 lines
4.7 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import {
showQiniuUploadProgress,
hideQiniuUploadProgress,
updateQiniuUploadProgress,
resetQiniuUploadProgress,
qiniuUploadProgressState
} from './qiniuUploadProgress.js'
export const QINIU_UPLOAD_URL = 'https://up-z2.qiniup.com'
export const QINIU_CDN_PREFIX = 'https://api.ccttiot.com/'
export function fetchQiniuToken($u) {
return $u.get('/common/qiniuToken').then((res) => {
if (res.code == 200 && res.data) {
return res.data
}
return null
}).catch(() => null)
}
export function parseQiniuUploadKey(res) {
if (!res || res.statusCode !== 200 || res.data == null || res.data === '') {
return ''
}
try {
const body = typeof res.data === 'string' ? JSON.parse(res.data) : res.data
if (!body || body.error) {
return ''
}
const key = body.key
if (typeof key !== 'string' || !key.trim()) {
return ''
}
return key.trim()
} catch (e) {
return ''
}
}
export function parseQiniuUploadUrl(res, cdnPrefix = QINIU_CDN_PREFIX) {
const key = parseQiniuUploadKey(res)
return key ? cdnPrefix + key : ''
}
/** 校验上传结果,不合法则抛错 */
export function assertValidUploadResult(result, returnKey = false) {
if (result == null || result === '') {
throw new Error('upload result empty')
}
const value = String(result).trim()
if (!value || value === 'undefined' || value.indexOf('undefined') !== -1) {
throw new Error('upload result invalid')
}
if (returnKey) {
return value
}
if (!/^https?:\/\//.test(value)) {
throw new Error('upload url invalid')
}
return value
}
function doUploadQiniuFile(options = {}) {
const {
filePath,
token,
key,
cdnPrefix = QINIU_CDN_PREFIX,
returnKey = false,
onProgress
} = options
return new Promise((resolve, reject) => {
if (!filePath) {
reject(new Error('missing filePath'))
return
}
if (!token) {
reject(new Error('missing token'))
return
}
if (!key) {
reject(new Error('missing key'))
return
}
const uploadTask = uni.uploadFile({
url: QINIU_UPLOAD_URL,
filePath,
name: 'file',
formData: {
token,
key
},
success: (res) => {
const uploadKey = parseQiniuUploadKey(res)
if (!uploadKey) {
reject(new Error('upload parse failed'))
return
}
try {
const result = returnKey ? uploadKey : cdnPrefix + uploadKey
resolve(assertValidUploadResult(result, returnKey))
} catch (e) {
reject(e)
}
},
fail: (err) => {
reject(err || new Error('upload request failed'))
}
})
if (uploadTask && uploadTask.onProgressUpdate && onProgress) {
uploadTask.onProgressUpdate(onProgress)
}
})
}
export function uploadQiniuFile(options = {}) {
const {
title = '上传中',
showProgress = true
} = options
if (showProgress) {
showQiniuUploadProgress(title)
}
return doUploadQiniuFile({
...options,
onProgress: showProgress ? updateQiniuUploadProgress : options.onProgress
}).then((result) => {
if (showProgress) {
qiniuUploadProgressState.progress = 100
qiniuUploadProgressState.speedText = '完成'
setTimeout(() => hideQiniuUploadProgress(), 200)
}
return result
}).catch((err) => {
if (showProgress) {
hideQiniuUploadProgress()
}
throw err
})
}
/**
* 带 token 刷新与失败重试的上传(默认最多 3 次:首次 + 重试 2 次)
* 仅在上传结果校验通过后才 resolve调用方可放心展示
*/
export async function uploadQiniuFileWithRetry($u, options = {}) {
const maxRetry = options.maxRetry != null ? options.maxRetry : 2
const showProgress = options.showProgress !== false
const title = options.title || '上传中'
const returnKey = !!options.returnKey
let token = options.token || null
let lastError = null
if (showProgress) {
showQiniuUploadProgress(title)
}
for (let attempt = 0; attempt <= maxRetry; attempt++) {
try {
if (!token) {
token = await fetchQiniuToken($u)
}
if (!token) {
throw new Error('no token')
}
if (attempt > 0 && showProgress) {
resetQiniuUploadProgress()
qiniuUploadProgressState.title = maxRetry > 0
? `${title}(重试 ${attempt}/${maxRetry}`
: title
}
const result = await doUploadQiniuFile({
...options,
token,
onProgress: showProgress ? updateQiniuUploadProgress : options.onProgress
})
const validResult = assertValidUploadResult(result, returnKey)
if (showProgress) {
qiniuUploadProgressState.progress = 100
qiniuUploadProgressState.speedText = '完成'
setTimeout(() => hideQiniuUploadProgress(), 200)
}
return validResult
} catch (e) {
lastError = e
token = null
if (attempt < maxRetry) {
token = await fetchQiniuToken($u)
}
}
}
if (showProgress) {
hideQiniuUploadProgress()
}
throw lastError || new Error('upload failed')
}