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.
相关产品推荐
相关产品推荐

