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') }