应直接校验tempFiles[0].size字节值,而非依赖sizeType参数;H5和部分小程序中该参数无效,且需按平台差异选择压缩方案并二次校验体积。

直接限制上传图片大小,不能只靠 uni.chooseImage 的 sizeType 参数——它在 H5 和部分小程序平台根本无效,且不提供精确字节控制。真正可靠的做法是:选完立刻校验 tempFiles[0].size,再结合平台特性做拦截或压缩。
用 tempFiles 拿到真实文件大小,别信扩展名或用户声明
很多开发者误以为检查文件后缀(如 .jpg)或靠肉眼判断“应该不大”,结果上传失败才报错。实际上,uni.chooseImage 返回的 res.tempFiles 数组里每个对象都带 size 字段(单位字节),这才是唯一可信依据。
-
size是原始文件体积,不是压缩后大小,也不受sizeType: ['compressed']影响(该参数在 H5 完全不生效,在微信小程序中仅对 JPG 有效,且压缩质量不可控) - 必须在
success回调里第一时间读取:const fileSize = res.tempFiles[0].size - 换算成 MB 要用
fileSize / 1024 / 1024,不是除以 1000;2MB 严格等于2 * 1024 * 1024 === 2097152字节 - 如果用户一次选多张,需遍历
res.tempFiles分别校验,不能只看第一张
超过 2MB 时,分平台决定是拦截还是压缩
不是所有场景都适合“直接拒绝”。业务允许时,优先压缩比提示重选更友好,但压缩方案必须按平台区分,否则会出错。
- 微信小程序:用
uni.compressImage,传入src: tempFilePaths[0],但注意它只支持 JPG,对 PNG/GIF 无效;压缩后仍需用uni.getFileInfo再次校验体积 - H5 端:必须用
canvas手动压缩,uni.compressImage不可用;关键点是压缩后生成Blob或转为 base64,再用File构造新文件对象供后续上传 - App 端:可直接用
uni.compressImage,兼容性最好,但安卓真机可能把 JPG 压成 WebP,需用uni.getImageInfo检查path后缀是否仍为.jpg或.png - 无论哪端,压缩后必须重新读取体积:
uni.getFileInfo({ filePath: compressedPath }),不能只依赖压缩 API 的“成功回调”
用 uni-file-picker 组件时,v-model 是唯一可控入口
组件本身不提供 maxSize 属性,想限制大小又不想回显超限文件,只能靠绑定的 v-model 数据做过滤——这是目前最稳定、无需改源码的方式。
- 监听
@select事件,拿到event.tempFiles - 立即过滤:
const validFiles = event.tempFiles.filter(f => f.size - 把
validFiles赋给v-model绑定的 ref 变量(类型应为UniFilePickerTempFile[]) - 如果过滤后数量变少,手动调
uni.showToast提示用户:“仅保留小于 2MB 的图片,其余已忽略” - 注意:不要用
clearFiles(index),因为@progress事件触发时机不可控,index很难准确对应
最容易被忽略的一点:压缩后的临时路径,必须是本地文件路径(以 uni://、tmp/ 或平台特定前缀开头),不能是 data: 或 http: 开头的 URL;否则 uni.uploadFile 会静默失败,服务端收不到文件或报 invalid image format。











