|
|
export const normalizeBase64Pure = (input) => {
|
|
|
let text = String(input ?? '').trim().replace(/\s/g, '')
|
|
|
if (!text) return ''
|
|
|
if (/^data:image\/[\w+.-]+;base64,/i.test(text)) {
|
|
|
text = text.replace(/^data:image\/[\w+.-]+;base64,/i, '')
|
|
|
}
|
|
|
return text
|
|
|
}
|
|
|
|
|
|
/** 补齐 padding,并兼容 URL-safe Base64 */
|
|
|
export const fixBase64ForDecode = (pure) => {
|
|
|
let text = String(pure ?? '').replace(/-/g, '+').replace(/_/g, '/')
|
|
|
const mod = text.length % 4
|
|
|
if (mod === 2) text += '=='
|
|
|
else if (mod === 3) text += '='
|
|
|
return text
|
|
|
}
|
|
|
|
|
|
export const getMimeTypeFromBase64 = (pure) => {
|
|
|
if (pure.startsWith('iVBORw0KGgo')) return 'image/png'
|
|
|
return 'image/jpeg'
|
|
|
}
|
|
|
|
|
|
export const extractImageBase64FromResponse = (result) => {
|
|
|
if (result === undefined || result === null) return ''
|
|
|
if (typeof result === 'string') return result
|
|
|
if (result.imageBase64) return result.imageBase64
|
|
|
if (result.data !== undefined && result.data !== null) {
|
|
|
return extractImageBase64FromResponse(result.data)
|
|
|
}
|
|
|
return ''
|
|
|
}
|
|
|
|
|
|
export const isWebPlatform = () => {
|
|
|
if (typeof window === 'undefined' || typeof document === 'undefined') {
|
|
|
return false
|
|
|
}
|
|
|
try {
|
|
|
const sys = uni.getSystemInfoSync()
|
|
|
return sys.uniPlatform === 'web' || sys.uniPlatform === 'h5'
|
|
|
} catch {
|
|
|
return true
|
|
|
}
|
|
|
}
|
|
|
|
|
|
const decodeBase64ToBytes = (pure) => {
|
|
|
const normalized = fixBase64ForDecode(pure)
|
|
|
const binary = atob(normalized)
|
|
|
const bytes = new Uint8Array(binary.length)
|
|
|
for (let i = 0; i < binary.length; i++) {
|
|
|
bytes[i] = binary.charCodeAt(i)
|
|
|
}
|
|
|
return bytes
|
|
|
}
|
|
|
|
|
|
const createBlobUrlFromBase64 = (pure, mime) => {
|
|
|
const bytes = decodeBase64ToBytes(pure)
|
|
|
const blob = new Blob([bytes], { type: mime })
|
|
|
const blobUrl = URL.createObjectURL(blob)
|
|
|
return {
|
|
|
src: blobUrl,
|
|
|
revoke: () => URL.revokeObjectURL(blobUrl),
|
|
|
}
|
|
|
}
|
|
|
|
|
|
const createDataUrlFromBase64 = (pure, mime) => {
|
|
|
const normalized = fixBase64ForDecode(pure)
|
|
|
return {
|
|
|
src: `data:${mime};base64,${normalized}`,
|
|
|
revoke: null,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
const tryWebDisplay = (pure, mime, resolve) => {
|
|
|
if (typeof window !== 'undefined' && typeof atob === 'function') {
|
|
|
try {
|
|
|
const blobResult = createBlobUrlFromBase64(pure, mime)
|
|
|
console.log('[face-image] 使用 Blob URL 展示')
|
|
|
resolve(blobResult)
|
|
|
return
|
|
|
} catch (error) {
|
|
|
console.log('[face-image] Blob URL 创建失败,回退 dataUrl', error)
|
|
|
}
|
|
|
}
|
|
|
console.log('[face-image] 使用 dataUrl 展示')
|
|
|
resolve(createDataUrlFromBase64(pure, mime))
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 将 Base64 转为可在页面中展示的图片地址
|
|
|
*/
|
|
|
export const loadFaceImageDisplaySrc = (base64Raw) => {
|
|
|
return new Promise((resolve, reject) => {
|
|
|
const pure = normalizeBase64Pure(base64Raw)
|
|
|
if (!pure) {
|
|
|
reject(new Error('图片 Base64 为空'))
|
|
|
return
|
|
|
}
|
|
|
|
|
|
const mime = getMimeTypeFromBase64(pure)
|
|
|
console.log('[face-image] base64 前缀:', pure.slice(0, 24), 'mime:', mime)
|
|
|
|
|
|
if (isWebPlatform()) {
|
|
|
tryWebDisplay(pure, mime, resolve)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if (typeof uni.base64ToTempFilePath === 'function') {
|
|
|
uni.base64ToTempFilePath({
|
|
|
base64Data: fixBase64ForDecode(pure),
|
|
|
extension: mime === 'image/png' ? 'png' : 'jpg',
|
|
|
success: (res) => {
|
|
|
console.log('[face-image] 使用临时文件展示:', res.tempFilePath)
|
|
|
resolve({
|
|
|
src: res.tempFilePath,
|
|
|
revoke: null,
|
|
|
})
|
|
|
},
|
|
|
fail: (err) => {
|
|
|
console.log('[face-image] base64ToTempFilePath 失败', err)
|
|
|
tryWebDisplay(pure, mime, resolve)
|
|
|
},
|
|
|
})
|
|
|
return
|
|
|
}
|
|
|
|
|
|
tryWebDisplay(pure, mime, resolve)
|
|
|
})
|
|
|
}
|