小工具知识网

当前位置: 首页 > 行业知识 > 解决uni.chooseImage勾选相册原图,使用pathToBase64方法转Base64,提示“targetSdkVersion设置>=29后在Android10+系统设备不支持当前路径”的问题

行业知识

解决uni.chooseImage勾选相册原图,使用pathToBase64方法转Base64,提示“targetSdkVersion设置>=29后在Android10+系统设备不支持当前路径”的问题

2026-11-10 10:45:43 来源:互联网转载

文章目录

    • 1.问题描述
    • 2.解决方案
      • 2.1 后端不使用 Base64 的格式接收图片
      • 2.2 在 uni.chooseImage API中添加 sizeType: ['compressed'] 配置,仅允许选择压缩图
      • 2.3 使用 uni.saveFile 方法另存图片后,再转 Base64
      • 3.原因探讨
      • 4.使用 uni.saveFile 方法另存图片,能够解决该问题的原因

        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

        • utils 下封装如下方法
           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 可以将选择自相册(系统公共目录)的文件,另存到应用沙盒目录中,由此便可以规避各种各样的操作问题了。

上一篇:宝塔面板怎么删除jdk?

下一篇:gmodexg服务器怎么玩?