必须分平台处理头像上传:微信小程序仅支持button open-type="chooseavatar"获取avatarurl,其他平台fallback uni.chooseimage并配置权限、sourcetype、路径校验及上传兜底逻辑。

直接上结论:不能只调 uni.chooseImage 就完事,必须分平台处理触发方式、权限配置、临时路径使用和上传校验,否则 iOS 静默失败、H5 点不动、安卓上传 400 或卡死。
微信小程序必须用 button open-type="chooseAvatar",别硬套 uni.chooseImage
微信基础库 2.21.2+ 后,wx.getUserProfile 不再返回真实头像,uni.chooseImage 也拿不到微信用户授权头像——它只读本地相册。想用微信头像,必须走官方 chooseAvatar 能力。
-
<button open-type="chooseAvatar"></button>是唯一合规入口,点击后弹窗含「从微信头像选」「拍照」「从手机相册选」三选项 -
onChooseAvatar回调里拿到的是e.detail.avatarUrl,路径形如wxfile://temp/xxx.jpg或http://temp/xxx.jpg,不是本地文件路径,不能直接传给uni.uploadFile - 若需兼容非微信平台(如支付宝、H5),得用条件编译:
#ifdef MP-WEIXIN分支走chooseAvatar,其他平台才 fallback 到uni.chooseImage
uni.chooseImage 在非微信平台要配权限、设 sourceType、校验 tempFiles[0].path
Android 和 iOS 真机上,uni.chooseImage 常静默失败,根本原因是没配 manifest 权限或参数写错。
- iOS 必须在
manifest.json → App SDK 配置 → 权限配置勾选「相册」;Android 要同时勾选「读取外部存储」和「相机」(部分厂商 ROM 即使只选图也会校验相机权限) -
sourceType: ['album', 'camera']必须显式声明,某些安卓机型默认只开相机,不写就进不了相册 - 成功回调里的字段名是
res.tempFiles[0].path,不是旧版的res.tempFilePaths[0],后者已弃用,用了会报错或路径为空 - 安卓真机相册路径可能含空格或中文,
uni.uploadFile会静默失败,可兜底用uni.getFileSystemManager().readFile读成ArrayBuffer再上传(仅小图)
上传前必须校验大小、类型、HTTPS,且 filePath 必须是临时路径
用户随手选张 10MB 原图或 PDF,后端常直接 400 或超时,前端却没反馈,体验断层。
- 用
uni.getImageInfo({ src: tempFilePath })提前读宽高和size(单位字节),拦截 >2MB 或宽高 >2000 的图 - 检查
res.type是否以image/开头,防止绕过accept限制上传非图文件 -
uni.uploadFile的url必须是完整 HTTPS 地址(H5 和小程序都强制),且后端接口要支持multipart/form-data -
header里必须带登录态 token,比如{ Authorization: uni.getStorageSync('token') },否则 401
上传成功后别只改页面变量,要同步 store、storage 和云数据库
常见错误是 this.avatarUrl = res.data.url 之后就结束了,切页再回来头像回退,或者下次登录还是旧图。
- 立即更新响应式状态(Vue 3 用
ref或store.avatar = res.data.url) - 调用
uni.setStorageSync('user_info', { ...userInfo, avatar: res.data.url })持久化到本地 - 如果用
uniCloud,必须同步调uniCloud.callFunction更新云数据库里的user.avatar字段,否则登录态拉取的仍是旧地址 - 上传中设
isUploading = true,按钮禁用并显示「上传中…」,避免重复点击发多请求
最易被忽略的是平台差异处理粒度:微信小程序的 chooseAvatar 返回路径不能直传 uploadFile,而 uni.chooseImage 在安卓上路径含空格会导致静默失败——这两个点不单独处理,90% 的线上头像上传功能都会在某个平台崩掉。











