本文详解 firebase storage 图片上传后无法获取下载 url 的常见错误(storageexception: object does not exist at location, http 404),核心原因是上传与下载使用了不一致的 storagereference,需确保二者指向同一文件路径。
本文详解 firebase storage 图片上传后无法获取下载 url 的常见错误(storageexception: object does not exist at location, http 404),核心原因是上传与下载使用了不一致的 storagereference,需确保二者指向同一文件路径。
在 Firebase Storage 中,getDownloadUrl() 并非“自动返回最新上传文件的 URL”,而是基于当前 StorageReference 实例所指向的具体路径发起请求。若该路径下实际不存在已上传的文件(或路径不匹配),就会触发 404 Not Found 错误 —— 这正是你遇到 StorageException: Code -13010, HttpResult: 404 的根本原因。
你的原始代码中存在关键逻辑偏差:
ref = FirebaseStorage.getInstance().getReference("photo"); // ref 指向 "photo/" 目录
// ❌ 错误:上传到子路径
ref.child(postId+"-"+fmNumber).putFile(result) // 实际上传至 "photo/123456-abc.jpg"
// ❌ 错误:却从父路径尝试获取 URL
ref.getDownloadUrl() // 尝试获取 "photo/" 目录本身的 URL → 404!ref.getDownloadUrl() 请求的是 "photo/" 这个目录级引用的下载链接(目录无下载 URL),而非你实际上传的文件 "photo/123456-abc.jpg"。Firebase Storage 要求 getDownloadUrl() 必须作用于确切的文件引用(即包含完整文件名的 StorageReference)。
✅ 正确做法是:复用同一个 StorageReference 实例完成上传与下载。推荐重构如下:
ActivityResultLauncher<String> imageSelect;
FirebaseStorage storage = FirebaseStorage.getInstance();
StorageReference baseRef = storage.getReference("photo"); // 基础引用
imageSelect = registerForActivityResult(
new ActivityResultContracts.GetContent(),
result -> {
if (result != null) {
imgPicker.setImageURI(result);
emptyImg = false;
Random random = new Random();
int post = random.nextInt(999999);
String postId = String.valueOf(post);
String fileName = postId + "-" + fmNumber;
// ✅ 创建唯一文件引用(关键!)
StorageReference fileRef = baseRef.child(fileName);
// ✅ 使用同一 fileRef 上传
fileRef.putFile(result)
.addOnSuccessListener(taskSnapshot -> {
// ✅ 使用同一 fileRef 获取下载 URL
fileRef.getDownloadUrl()
.addOnSuccessListener(uri -> {
image = uri.toString();
System.out.println("Download URL: " + image);
Toast.makeText(FromActivity.this, "Image Upload Successful", Toast.LENGTH_SHORT).show();
uploadComplete = true;
})
.addOnFailureListener(e -> {
// ⚠️ 注意:此处可能因权限或网络失败,需处理
Toast.makeText(FromActivity.this, "Failed to get download URL: " + e.getMessage(),
Toast.LENGTH_LONG).show();
Log.e("Storage", "Get download URL failed", e);
});
})
.addOnFailureListener(e -> {
Toast.makeText(FromActivity.this, "Upload failed: " + e.getMessage(),
Toast.LENGTH_LONG).show();
Log.e("Storage", "Upload failed", e);
});
} else {
Toast.makeText(FromActivity.this, "You didn't select any image", Toast.LENGTH_SHORT).show();
imgPicker.setImageResource(R.drawable.profile);
uploadComplete = false;
}
}
);? 关键要点总结:
- 引用一致性:上传 putFile() 和获取 getDownloadUrl() 必须使用完全相同的 StorageReference 对象(如 fileRef),而非其父级或兄弟级引用。
- 路径准确性:确保 child(...) 中的文件名不含非法字符(如 /, \, #, ?, [, ]),建议使用 Uri.getLastPathSegment() 或 UUID.randomUUID().toString() 生成安全文件名。
- 权限检查:确认 Firebase Storage 安全规则允许读取(allow read: if request.auth != null; 或按需配置)。
- 异步依赖:getDownloadUrl() 是异步操作,必须在 putFile().addOnSuccessListener 内部调用,不可在上传回调外执行。
? 进阶建议:
- 使用 taskSnapshot.getMetadata().getReference().getDownloadUrl() 可直接从上传成功回调中获取 URL(更简洁且避免重复引用):
fileRef.putFile(result) .addOnSuccessListener(taskSnapshot -> { // ✅ 更推荐:从 taskSnapshot 直接获取引用并取 URL taskSnapshot.getMetadata().getReference().getDownloadUrl() .addOnSuccessListener(uri -> image = uri.toString()); }); - 避免 Random.nextInt() 生成文件名(存在哈希冲突风险),优先采用 UUID 或服务端时间戳+随机数组合。
遵循以上原则,即可彻底解决 Object does not exist at location 的 404 错误,稳定获取 Firebase Storage 图片下载地址。

















