3步教你从小程序内快速获取高清原图
在小程序开发中,获取图片这件事看起来简单,但实际踩坑的人特别多。很多开发者照着文档写代码,结果发现拿到的路径要么是临时文件、要么根本打不开。今天咱们就把这个问题拆开揉碎,从底层逻辑到实战操作,把“获取小程序图片”这件事讲透。
一、先搞清楚你要获取哪类图片
小程序里的图片来源分三种:
第一种:用户手机相册里的图片。比如头像上传、晒图功能。这种用 wx.chooseImage 或 wx.chooseMedia 调起系统选择器,拿到的路径是 wxfile:// 开头的临时文件。
第二种:小程序包内的图片。就是放在项目 images 文件夹下的资源,用相对路径引用,比如 /images/logo.png。这种最简单,但注意包体积不能超过2M,大图建议用网络图。
第三种:网络图片。比如从CDN加载的 https://example.com/pic.jpg。这种需要配置域名白名单,而且直接拿URL就能用,但要注意防盗链和缓存策略。
混淆的是:wx.chooseImage 返回的临时路径,并不是永久有效的。它只在当前小程序生命周期内有效,一旦重启或者手动清除缓存,路径就失效了。所以如果你想长期保存,必须上传到服务器,或者用 wx.saveFile 转存成本地缓存文件。
咱们用最常见的场景举例:用户点击按钮,从相册选一张图,然后显示在页面上。直接上代码,每一步都带注释:
第一步:在 .wxml 里放一个按钮和图片容器
<button bindtap="chooseImage">选择图片</button>
<image src="{{imagePath}}" mode="aspectFit" style="width:200px;height:200px;"></image>
第二步:在 .js 里写选择逻辑
Page({
data: {
imagePath: '' // 初始为空
},
chooseImage() {
const that = this;
wx.chooseImage({
count: 1, // 一次选1张,最多9张
sizeType: ['original', 'compressed'], // 可选原图或压缩图
sourceType: ['album', 'camera'], // 从相册或相机
success(res) {
// res.tempFilePaths 是临时文件路径数组
const tempPath = res.tempFilePaths[0];
that.setData({
imagePath: tempPath
});
// 到这里图片已经显示在页面上了
// 但注意:这个路径是临时的!
},
fail(err) {
console.log('选图失败', err);
}
});
}
});
关键点:res.tempFilePaths 返回的是数组,哪怕你只选了一张图,也要用索引取。另外 sizeType 建议选 compressed,因为原图可能非常大,上传时容易超时,而且用户手机流量也心疼。压缩后的图片质量通常够用,除非你做的是专业修图工具。
上面拿到的临时路径,如果你只是临时展示一下,没问题。但如果你刷新页面或者退出小程序再进来,图片就没了。这时候需要 wx.saveFile 把图片存到本地缓存。
wx.saveFile({
tempFilePath: tempPath, // 临时路径
success(res) {
// res.savedFilePath 是本地缓存路径,永久有效
const savedPath = res.savedFilePath;
that.setData({
imagePath: savedPath
});
// 注意:本地缓存有大小限制,默认10MB,超了会清理旧文件
},
fail(err) {
console.log('保存失败', err);
}
});
这里有个坑:wx.saveFile 保存的文件,在微信存储空间里,不同小程序之间是隔离的。而且用户可以在微信设置里手动清理小程序缓存,一旦清理,所有本地文件都会消失。所以如果你需要图片长期存在(比如用户头像),必须上传到自己的服务器。
绝大多数小程序都需要把图片传到后端。用 wx.uploadFile 可以实现:
wx.uploadFile({
url: 'https://your-api.com/upload', // 你的上传接口
filePath: tempPath, // 临时路径
name: 'file', // 后端接收的字段名
formData: {
userId: '123' // 可以附带其他参数
},
success(res) {
const data = JSON.parse(res.data);
console.log('上传成功,返回的URL是', data.url);
// 把返回的URL存到全局或数据库
},
fail(err) {
console.log('上传失败', err);
}
});
常见错误:errMsg: "uploadFile:fail"。原因通常是:
1. 后台接口没配置白名单,需要在微信公众平台“开发设置”里添加服务器域名。
2. filePath 传成了本地缓存路径,但 uploadFile 只认临时路径。如果你之前用 saveFile 存过,想上传时得重新用 wx.chooseImage 获取临时路径,或者用 wx.getFileSystemManager().readFile 读取本地文件再上传。
3. 后端没处理好图片格式,上传前最好用 wx.getImageInfo 获取图片的宽高和类型,传给后端做校验。
有时候我们需要显示其他域名的图片,比如用户从网络分享的URL。直接 src="{{url}}" 可能显示不出来,因为微信限制了图片域名白名单。解决办法:
1. 在 app.json 的 networkTimeout 里配置超时,但这不是根本。
2. 最靠谱的是用 wx.downloadFile 把网络图片下载到本地临时路径:
wx.downloadFile({
url: 'https://external-site.com/pic.jpg',
success(res) {
// res.tempFilePath 是下载后的临时路径
that.setData({
imagePath: res.tempFilePath
});
},
fail(err) {
console.log('下载失败', err);
// 可能是域名没配置白名单,或者图片太大
}
});
注意:downloadFile 也有域名白名单限制,必须先在微信公众平台配置。而且微信对图片大小有限制,超过10MB可能被拒绝。另外,downloadFile 返回的也是临时路径,重启后失效,如果你需要长期用,同样要 saveFile 或上传。
为了让你更清晰,咱们列个对比:
用户相册图片:适合头像、晒图、证件照上传。性能中等,因为涉及用户交互(选图、压缩、上传)。注意点:压缩质量可调,sizeType: ['compressed'] 能减小体积;用户拒绝授权时需引导开启相册权限。
包内图片:适合图标、背景、小素材。性能最好,因为本地加载无网络延迟。但包体积有限,大图必须转网络图。注意:image 标签的 src 用绝对路径 /images/xxx.png,别用相对路径。
网络图片:适合商品图、文章配图、动态内容。性能取决于CDN和网络环境,可以用 lazy-load 属性做懒加载。注意:防盗链可以通过加签名参数解决;缓存策略用 wx.setStorage 存URL列表,避免重复下载。
很多开发者只关心“拿到图”,却忽略了图片质量对性能的影响。一张5MB的原图,在小程序里加载会卡到怀疑人生。建议在 wx.chooseImage 之后,用 wx.compressImage 进一步压缩:
wx.compressImage({
src: tempPath, // 临时路径
quality: 80, // 0-100,80是平衡点
success(res) {
// res.tempFilePath 是压缩后的临时路径
// 注意:压缩后文件可能比原图还大(极少数情况),建议加个判断
if (res.tempFilePath) {
that.setData({
imagePath: res.tempFilePath
});
}
}
});
还有一个冷门但实用的功能:wx.cropImage。微信官方没有直接提供裁剪API,但你可以用 canvas 实现。比如用户选图后,弹出一个裁剪框,让用户拖动选择区域,然后通过 canvas 的 drawImage 方法截取并导出。这个方案适合做头像上传时的圆形裁剪或比例固定裁剪。
你可能会遇到这些情况:
情况1:选图成功但图片显示不出来。检查 image 标签的 src 是否绑定了正确的路径,临时路径是否被覆盖。另外 mode 属性设置不当可能导致图片拉伸或裁剪,建议用 aspectFill 或 aspectFit。
情况2:上传图片一直失败,报“网络错误”。先用开发者工具的“网络”面板看请求是否发出,再看后端返回的状态码。如果是400,可能是参数名不对;如果是500,可能是后端处理图片超时,建议压缩后再上传。
情况3:本地缓存图片突然没了。用户清理缓存或者小程序存储空间不足时,微信会自动清理旧文件。解决办法:在 wx.saveFile 成功时,把返回的 savedFilePath 存到 wx.setStorage,下次启动时检查是否存在,如果不存在就重新下载或提示用户重新选图。
最后说一句:小程序图片获取看似基础,但涉及临时路径、本地缓存、上传策略、权限管理等多个环节。每多了解一个细节,就能少踩一个坑。建议你动手写一个完整的小案例,从选图、压缩、保存到上传,走通全流程,以后再遇到图片相关需求,就能从容应对了。

