You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从相册多选图片上传Firebase Storage遇ENOENT错误求助

问题原因分析

错误核心是把Content Uri当成文件系统路径处理:

  • 相册返回的content://开头的Uri是内容提供者的访问标识,并非直接的文件系统路径,无法通过File(listImg[i].toString())创建有效文件对象。
  • 额外问题:onActivityResult处理单张图片时,错误提取data.data!!.path再转Uri,导致Uri格式失效。
修复步骤

1. 修正onActivityResult的Uri存储逻辑

单张图片直接使用返回的原始Uri,不要提取path再转换,同时修正多选数量判断逻辑:

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    if (requestCode == GALLERY_PIC && resultCode == RESULT_OK) {
        if(data?.clipData != null) {
            val selectedCount = data.clipData?.itemCount ?: 0
            if(selectedCount <=6 && listImg.size + selectedCount <=6) {
                for (i in 0 until selectedCount) {
                    val uri = data.clipData!!.getItemAt(i).uri
                    listImg.add(uri)
                }
                myAdapterForImg.notifyDataSetChanged()
            } else {
                Toast.makeText(ctx,"最多只能选择6张图片",Toast.LENGTH_LONG).show()
            }
        } else if(data?.data != null) {
            val uri = data.data!!
            if(listImg.size +1 <=6) {
                listImg.add(uri)
                Log.d("PATH",uri.toString())
                myAdapterForImg.notifyDataSetChanged()
            } else {
                Toast.makeText(ctx,"最多只能选择6张图片",Toast.LENGTH_LONG).show()
            }
        }
    }
}

2. 修正Firebase上传逻辑

直接使用列表中存储的原始Content Uri调用putFile,无需转成File,同时修正下载链接的异步获取逻辑:

for (i in 0 until listImg.size) {
    val imageUri = listImg[i]
    val riversRef = storageRef.child("images/${imageUri.lastPathSegment}")
    val uploadTask = riversRef.putFile(imageUri)
    
    uploadTask.addOnProgressListener { taskSnapshot ->
        val progress = (100.0 * taskSnapshot.bytesTransferred) / taskSnapshot.totalByteCount
        Log.d("TAG", "Upload is $progress% done")
        progressDialog.setMessage("已上传.. " + progress.toInt() + "%")
    }.addOnPausedListener {
        Log.d("TAG", "上传已暂停")
    }.addOnFailureListener {
        Log.e("ERROR:",it.toString())
        progressDialog.dismiss()
    }.addOnSuccessListener {
        progressDialog.dismiss()
        riversRef.downloadUrl.addOnSuccessListener { downloadUri ->
            Log.d("DownloadURL:" ,downloadUri.toString())
        }
    }
}

3. 适配Android 10+存储权限

从Android 10(API 29)开始,媒体文件访问无需申请READ/WRITE_EXTERNAL_STORAGE权限,可在Manifest中添加版本限制优化权限声明:

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="28"/>
关键知识点
  • content://开头的Content Uri是Android内容提供者的访问标识,代表应用共享资源,并非本地文件路径,不能直接转为File对象。
  • Firebase Storage的putFile方法支持直接传入Content Uri,内部会自动处理资源读取,无需手动转换文件路径。

内容的提问来源于stack exchange,提问作者Captai-N

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 01:20:38