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

Android端Firebase图片上传报StorageException(-13010/404)问题求助

问题根源

你遇到的核心问题是Android 10(API 29)及以上版本中,MediaStore.Images.Media.DATA字段已被废弃,通过它获取的文件路径大概率无效,导致转换出的File对象实际不存在,Firebase Storage自然找不到文件抛出404错误。另外你完全没必要绕"Content URI→File→File URI"的弯路,Firebase直接支持Content URI上传。


解决方案

方案1:直接用拍照返回的Content URI上传(推荐)

删掉多余的uriToFile转换步骤,直接把拍照得到的Content URI传给上传方法,这是最简洁可靠的方式:

private fun uploadImage(imageUri: Uri?) {
    if(imageUri != null) {
        val storageRef = Firebase.storage.reference
        // 从Content URI中提取文件名,或自定义文件名
        val fileName = getFileNameFromUri(imageUri) ?: "uploaded_image_${System.currentTimeMillis()}.jpg"
        val imageRef = storageRef.child("images/$fileName")
        // 直接传入Content URI,无需转File
        val uploadTask = imageRef.putFile(imageUri)

        uploadTask.addOnCompleteListener { task ->
            if(task.isSuccessful) {
                imageRef.downloadUrl.addOnSuccessListener { uri ->
                    downloadUrl = uri.toString()
                }
            } else {
                Toast.makeText(this, "이미지 업로드에 실패하였습니다.", Toast.LENGTH_SHORT).show()
                // 打印详细错误便于排查
                task.exception?.let { Log.e("UploadFail", it.localizedMessage ?: "未知错误") }
            }
        }
    }
}

// 辅助方法:从Content URI获取文件名
private fun getFileNameFromUri(uri: Uri): String? {
    var fileName: String? = null
    contentResolver.query(uri, null, null, null, null)?.let { cursor ->
        if(cursor.moveToFirst()) {
            val nameColumnIndex = cursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME)
            fileName = cursor.getString(nameColumnIndex)
        }
        cursor.close()
    }
    return fileName
}

方案2:若确实需要File对象(修复uriToFile方法)

如果业务逻辑必须用到File,不要依赖废弃的DATA字段,改用ContentResolver将流复制到APP私有缓存目录生成File:

fun uriToFile(context: Context, uri: Uri?): File? {
    uri ?: return null
    return try {
        val inputStream = context.contentResolver.openInputStream(uri) ?: return null
        // 在APP私有缓存目录创建临时文件
        val tempFile = File(context.cacheDir, "temp_img_${System.currentTimeMillis()}.jpg")
        val outputStream = FileOutputStream(tempFile)
        inputStream.copyTo(outputStream)
        // 关闭流
        inputStream.close()
        outputStream.close()
        tempFile
    } catch (e: Exception) {
        Log.e("UriToFileError", e.localizedMessage ?: "转换失败")
        null
    }
}

这个方法生成的File存在于APP私有目录,Firebase可以正常访问。

权限补充检查

  • Android 10+:无需申请READ_EXTERNAL_STORAGE/WRITE_EXTERNAL_STORAGE权限,通过Content URI访问媒体文件是系统允许的。
  • Android 9及以下:需要在Manifest中声明并动态申请READ_EXTERNAL_STORAGE权限。

内容的提问来源于stack exchange,提问作者Name. Parky.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 15:22:52