从相册多选图片上传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
相关产品推荐
相关产品推荐

