1.标题描述
上传图片时,后端吸收的参数类型为 Base64,于是我们便使用 uniapp 中的 uni.chooseImage API,搭配 image-tools 插件的 pathToBase64 方法来实现传递 Base64 格式图片的业务需求。
- // 业务代码
- import { pathToBase64 } from '@/utils/image-tools.js'
- uni.chooseImage({
- count: 1,
- sourceType: ['camera', 'album'],
- async success(res) {
- let ewm = res.tempFilePaths[0]
- ewm = await pathToBase64(ewm)
- const data = {
- formData: {
- ewm
- }
- }
- const {data: res} = await _this.networkApi(data)
- // 下方省略
- },
- })
复制代码 H5 端没有标题,但在安卓APP 中,当用户勾选原图之后,便出现了标题,经调试排查,发现 await pathToBase64(ewm) 抛出了一个非常
- {
- "type": "error",
- "bubbles": false,
- "cancelBubble": false,
- "cancelable": false,
- "lengthComputable": false,
- "loaded": 0,
- "total": 0,
- "target": {
- "fileName": "/storage/emulated/0/Pictures/Gallery/owner/xxx/IMG_20240202_133858.jpg",
- "readyState": 2,
- "result": null,
- "error": {
- "code": 15,
- "message": "targetSdkVersion设置>=29后在Android10+系统设备不支持当前路径。请更改为应用运行路径!具体请看:https://ask.dcloud.net.cn/article/36199"
- },
- "onloadstart": null,
- "onprogress": null,
- "onload": "function() { [native code] }",
- "onabort": null,
- "onerror": "function() { [native code] }",
- "onloadend": null
- }
- }
复制代码 2.解决方案
经过阅读文章 https://ask.dcloud.net.cn/article/id-36199,并经过有关尝试后,有以下三种解决方案
2.1 后端不使用 Base64 的格式吸收图片
2.2 在 uni.chooseImage API中添加 sizeType: [‘compressed’] 配置,仅允许选择压缩图
- // 业务代码
- import { pathToBase64 } from '@/utils/image-tools.js'
- uni.chooseImage({
- count: 1,
- sourceType: ['camera', 'album'],
- // 添加该配置,仅使用 压缩图
- sizeType: ['compressed'],
- async success(res) {
- let ewm = res.tempFilePaths[0]
- ewm = await pathToBase64(ewm)
- const data = {
- formData: {
- ewm
- }
- }
- const {data: res} = await _this.networkApi(data)
- // 下方省略
- },
- })
复制代码 2.3 使用 uni.saveFile 方法另存图片后,再转 Base64
- export const saveFileSync = (tempFilePath) => {
- return new Promise((resolve, reject) => {
- uni.saveFile({
- tempFilePath,
- success: function (file) {
- resolve(file.savedFilePath)
- },
- fail: function (error) {
- reject(error)
- }
- })
- })
- }
复制代码
- 使用 saveFileSync,将选择的图片另行生存到本地,并获取生存的地址
- // 业务代码
- import { pathToBase64 } from '@/utils/image-tools.js'
- import { saveFileSync } from '@/utils/file.js'
- uni.chooseImage({
- count: 1,
- sourceType: ['camera', 'album'],
- async success(res) {
- let ewm = res.tempFilePaths[0]
- // 使用 saveFileSync,将选择的图片另行保存到本地,并获取保存的地址
- const path = await saveFileSync(ewm)
- ewm = await pathToBase64(path)
- const data = {
- formData: {
- ewm
- }
- }
- const {data: res} = await _this.networkApi(data)
- // 下方省略
- },
- })
复制代码 3.原因探究
声明:下方大多是我排查BUG、探索标题产生原因的过程记录,开发任务重的同学可以先去忙哈~
- 用户通过相册选择图片的地址的绝对路径为 file:///storage/emulated/0/Pictures 开头,经过阅读文章 https://ask.dcloud.net.cn/article/id-36199 可以知道,该目录属于体系公共目录
- 文章中提到:“andorid 11逼迫实行分区存储。不允许应用读写操纵非应用沙盒目录和体系公共目录下的资源文件。dcloud已对分区存储机制做了适配工作。但也增加了开发者对文件目录操纵的规则。在分区存储的环境下分出两个可操文件数据目录 体系公共目录 和 应用沙盒目录。”
- 大概意思就是 安卓自身不允许应用访问自身存储空间(应用沙盒目录)之外的内容,dcloud 对分区存储机制进行了优化,除了自身存储空间外,体系公共目录也能通过一定手段来进行读写
- 对于体系公共目录,“当我们拥有权限,也能通过路径直接访问。”,这一点,大概就是体系在读写相册前,需要授权的原因,在完成授权后,我们便能够读写 相册 等体系公共目录
- 由此我推测,当用户勾选了原图之后, dcloud 对分区存储机制的优化失效了,应用无法访问体系公共目录,导致抛出非常,但经过尝试发现,其他未进行 Base64 转化的地方,勾选原图也可以实现图片的正常上传
- 于是又对文章阅读了两遍,发现对 体系公共目录的描述中有如许一句话
- 以是推测 image-tools 中的 pathToBase64 方法,存在对体系公共目录的文件进行了写操纵,但经过阅读源码、查阅有关文档发现,应该不存在写操纵,也就不会出现对体系公共目录操纵越权的举动
- export function pathToBase64(path) {
- // 省略其他代码
- if (typeof plus === 'object') {
- plus.io.resolveLocalFileSystemURL(
- getLocalFilePath(path),
- function(entry) {
- entry.file(
- function(file) {
- var fileReader = new plus.io.FileReader()
-
- fileReader.onload = function(data) {
- resolve(data.target.result)
- }
-
- fileReader.onerror = function(error) {
- reject(error)
- }
-
- fileReader.readAsDataURL(file)
- },
- function(error) {
- reject(error)
- }
- )
- },
- function(error) {
- reject(error)
- }
- )
-
- return
- }
- // 省略其他代码
- }
复制代码
- 至此,我对“解决 uni.chooseImage 勾选相册原图,搭配 image-tools 插件的 pathToBase64 方法转 Base64,提示“targetSdkVersion设置>=29后在Android10+体系设备不支持当前路径”的标题”的探究就无果而终了
- 有知道原因的同学或先辈可以在批评区留言指教一番,先行感谢~
4.使用 uni.saveFile 方法另存图片,能够解决该标题标原因
接上文,应用程序在分区存储的环境下,分出了两个可操做文件数据目录:体系公共目录 和 应用沙盒目录,只管 dcloud 对分区存储机制做了适配工作,但体系公共目录的操纵权限天然不如应用沙盒目录来的广泛、自由
而使用 uni.saveFile 可以将选择自相册(体系公共目录)的文件,另存到应用沙盒目录中,由此便可以规避各种各样的操纵标题了。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |