uni-app图片路径和base64转换
uni-app 做图片处理时,路径问题很容易踩坑,同一张图片在 H5、App、小程序里面可能完全不是一种处理方式
图片编辑组件里面有一个很重要的工具文件。
它主要做两件事:
1 | pathToBase64() |
一开始会觉得这两个方法没什么特别。
但是做跨端以后会发现,图片路径和 base64 的转换其实是很关键的一层。
为什么需要转换
用户选择图片后,uni.chooseImage 会返回临时路径。
但是不同端返回的路径格式不一样。
H5 里可能是浏览器可以访问的 blob 或本地地址。
App 里可能是 _doc、_www、file://、/storage/emulated/0/ 这类路径。
微信小程序里又是小程序自己的临时文件路径。
如果只是拿这个路径直接给所有端使用,很容易某一端正常,另一端就加载失败。
所以组件里会把本地图片先转成 base64。
base64 对页面显示和截图来说更稳定。
本地路径处理
App 端里面,本地路径还需要先转换一下。
工具方法里有一个 getLocalFilePath:
1 | function getLocalFilePath(path) { |
这个方法主要是为了把不同形式的本地路径统一成 App 能识别的路径。
这就是 uni-app 跨端项目里经常遇到的问题。
代码写起来像是一套,但是底层文件系统不是一套。
H5转base64
H5 里面比较常见的方式是 FileReader。
代码里面是通过 XMLHttpRequest 拿到 blob,然后用 FileReader 读取:
1 | var xhr = new XMLHttpRequest() |
这里得到的结果就是 base64。
H5 这条线相对直接,因为浏览器本身就有这些能力。
App转base64
App 端不能只按浏览器方式来。
这里要走 plus.io:
1 | plus.io.resolveLocalFileSystemURL(getLocalFilePath(path), function(entry) { |
这也是为什么组件里会判断:
1 | if (typeof plus === 'object') { |
plus 是 App 端的能力。
如果项目跑在 H5 或小程序里,就不能直接使用它。
微信小程序转base64
微信小程序里面要走文件系统管理器:
1 | wx.getFileSystemManager().readFile({ |
这里需要自己补上 base64 的头:
1 | data:image/png;base64, |
否则后面当作图片显示时可能识别不了。
base64转路径
编辑完成后,html2canvas 生成的是 base64。
但是保存到相册时,uni.saveImageToPhotosAlbum 要的是本地路径。
所以还要把 base64 转回路径。
H5 里可以转成 blob 地址:
1 | return resolve( |
App 端可以用 plus.nativeObj.Bitmap:
1 | var bitmap = new plus.nativeObj.Bitmap(fileName) |
微信小程序则是写入用户临时目录:
1 | var filePath = wx.env.USER_DATA_PATH + '/' + fileName |
三端处理方式完全不一样。
这也是为什么我把它单独封装成工具函数。
为什么不统一都用base64
base64 看起来跨端都能用,但它也有问题。
- 字符串很长
- 不适合频繁传递
- 保存相册 API 不一定接受
- 上传文件时通常还是需要本地路径或文件对象
所以组件内部可以用 base64 做中间状态,但对外最好还是返回本地路径。
这次组件返回的是:
1 | { |
这样使用方可以按自己的场景选择。
总结
uni-app 的图片路径问题,本质上是多端文件系统差异。
H5 有浏览器 API。
App 有 plus 能力。
小程序有自己的文件系统。
所以图片编辑组件不能只写一种路径处理方式。
先把路径转成 base64,编辑完成后再把 base64 转成本地临时路径,这样整个流程会稳很多。
以上就是我对 uni-app 图片路径和 base64 转换的理解,如有错误,欢迎大佬指出。