/** * 把后端返回的 data URI / 纯 base64 写成小程序本地文件 * 为什么:微信 不能稳定渲染 data:image/...;base64(体积大或带 chunk_split 换行时真机空白), * 写成 USER_DATA_PATH 后用本地路径展示,无需上传 OSS * 放主包 utils:代付码弹窗走 easycom 必须在主包 components,工具与组件同层避免分包互引 */ /** * 取可写的用户目录(真机优先 wx.env,H5/开发工具兜底 uni.env) * @returns {string} */ function getUserDataPath() { if (typeof wx !== 'undefined' && wx.env && wx.env.USER_DATA_PATH) { return wx.env.USER_DATA_PATH } if (uni.env && uni.env.USER_DATA_PATH) { return uni.env.USER_DATA_PATH } return '' } /** * data URI / 纯 base64 写入本地临时文件,返回可供 绑定的路径 * @param {string} base64 完整 data:image/xxx;base64,xxx 或纯 base64(可含 chunk_split 空白) * @param {string} prefix 文件名前缀,默认 img * @returns {Promise} 本地文件路径 */ export function base64ToLocalPath(base64, prefix = 'img') { return new Promise((resolve, reject) => { const raw = String(base64 || '').trim() if (!raw) { reject(new Error('图片数据为空')) return } const root = getUserDataPath() if (!root) { reject(new Error('无法获取临时目录')) return } const match = /^data:image\/(\w+);base64,/i.exec(raw) const format = (match && match[1] ? match[1] : 'png').toLowerCase() const body = (match ? raw.slice(match[0].length) : raw).replace(/\s/g, '') if (!body) { reject(new Error('图片数据无效')) return } const filePath = `${root}/${prefix}_${Date.now()}.${format}` uni.getFileSystemManager().writeFile({ filePath, data: body, encoding: 'base64', success() { resolve(filePath) }, fail() { reject(new Error('本地图片写入失败')) }, }) }) } /** * 删除本地临时文件;已删或不存在不抛错,避免阻断关弹窗 * @param {string} filePath writeFile 得到的路径 * @returns {Promise} */ export function unlinkLocalFile(filePath) { return new Promise((resolve) => { if (!filePath) { resolve() return } uni.getFileSystemManager().unlink({ filePath, success() { resolve() }, fail() { resolve() }, }) }) }