小程序图片闪退本质是内存超限与渲染崩溃叠加,需同步控制体积、尺寸、格式及加载时机;uni.chooseimage禁用original,安卓用compressed,ios需canvas二次压缩;webp须转码为jpeg;所有图片须校验路径、尺寸与格式。

小程序端图片过大导致闪退,本质是内存超限 + 渲染崩溃双叠加,不是“传不上去”而是“渲染就崩”,必须同时控制体积、尺寸、格式和加载时机。
uni.chooseImage 用错参数会直接触发闪退
很多开发者在微信小程序里写 uni.chooseImage({ sourceType: ['camera'], sizeType: ['original'] }),结果拍照后 App 闪退——尤其在华为、小米等中低端机型上。这是因为 sizeType: ['original'] 返回的是未经压缩的原始图,4000×3000 的 JPEG 在解码渲染时瞬间吃掉 100MB+ 内存,系统直接 kill 进程。
- 安卓真机务必改用
sizeType: ['compressed'],这是微信原生支持的压缩路径,不走 JS 解码,最稳 - iOS 上
compressed效果有限,需额外加 canvas 二次压缩(见下一条) - 别信“
count: 1就安全”——单张 8MB 的 compressed 图在部分安卓机仍会闪退
canvas 压缩后没校验临时路径就上传,等于埋雷
你写了 canvas 压缩逻辑,canvas.toTempFilePath 回调也进了,但上传还是失败或闪退?大概率是生成的路径根本不是合法临时文件路径。
- 检查返回的
tempFilePath是否以wxfile://或http://开头——如果是,说明你误用了toDataURL或 blob URL,uni.uploadFile只认本地临时路径 - 必须用
uni.getFileInfo({ filePath: tempFilePath })查真实体积,不能只看“压缩回调成功” - 安卓真机常见陷阱:canvas 绘制后未调用
draw就直接toTempFilePath,返回空路径,后续操作全崩
rich-text 里嵌大图会静默崩溃,image 标签也一样
<rich-text></rich-text> 渲染 HTML 时,如果里面含 <img src="..."> 指向一张 5MB 的图,小程序基础库会在后台解码并尝试渲染——这个过程不报错、不提示、直接闪退。同理,<image></image> 绑定一个超大 base64 或本地路径,也会卡死。
- 服务端返回 rich-text 内容前,必须过滤掉所有宽高 > 2000px 或体积 > 1.5MB 的
<img>标签,并替换为占位图 + 点击放大逻辑 - 前端渲染前做一次 DOM 遍历:
document.querySelectorAll('img')拿到 src,用uni.getImageInfo异步查尺寸,超限则先隐藏再懒加载 - 绝对不要把 base64 直接塞进
<image :src="base64Str"></image>,>100KB 就可能闪退;优先转成临时文件路径再用
webp 格式在安卓上是隐形炸弹
安卓真机从相册选图,uni.chooseImage 返回的 tempFilePath 后缀常是 .webp,但你的后端只接收 .jpg 或 .png。更糟的是,部分安卓机型(如华为 EMUI)的 webp 解码器有 bug,一渲染就 crash,且无任何日志。
- 拿到
tempFilePath后,先用uni.getImageInfo读取path字段,截取后缀判断是否为webp - 是 webp 就必须走 canvas 转码:drawImage → toDataURL("image/jpeg", 0.8) →
uni.base64ToTempFile生成新路径 - 别依赖后端转换——前端传 webp 过去,后端转 jpg,中间链路断了就白忙
真正容易被忽略的点:闪退往往发生在“看似成功”的环节——canvas 回调执行了、tempFilePath 有值、uploadFile 发出去了,但实际渲染线程早已崩在后台。所以每一步都要加体积/格式/路径三重校验,而不是只盯“有没有报错”。











