Firebase Storage getFile(content:// URI)抛异常,求远程拉取解决方案
getFile(Uri) and content:// URIs Hey Andrew, let's break down why you're hitting this java.io.IOException: No such file or directory error and how to resolve it for your use case (falling back to Firebase Storage when local content is unavailable).
The Root Cause
Firebase Storage's getFile(Uri) method is built to work with file system URIs (those starting with file:///), which point directly to a file on your device's storage. It doesn't support content:// URIs—these are managed by Android's Content Providers and don't map to a direct, accessible file path that Firebase can resolve. That's exactly why the error is popping up.
Solution 1: Use getFile(File) Instead of getFile(Uri) (Simplest Approach)
If you already have a local File object (like your test file f), skip converting it to a content:// URI entirely. Firebase Storage has an overload of getFile() that accepts a File directly, which avoids URI type issues:
// Your existing local File creation code File f = new File(context.getFilesDir(), "my-local-file"); // Example private storage path // Reference to your target Firebase Storage file StorageReference storageRef = FirebaseStorage.getInstance() .getReference("ysCwjgc0zGfUNuZimHGaun0MzlP2/files/document-d876e8aa-4b6a-45ed-b2f1-dfd2fbf21360"); // Download directly to your local File storageRef.getFile(f) .addOnSuccessListener(taskSnapshot -> { // Success: File is now saved locally at f's path Uri localContentUri = Uri.fromFile(f); // Convert to URI if you need it later }) .addOnFailureListener(e -> { // Handle download failure Log.e("FirebaseStorage", "Download failed", e); });
This is the most reliable method because it works directly with the file system, no URI conversion needed.
Solution 2: Convert content:// URI to a File System Path (If You Must Use a Content URI)
If you only have a content:// URI (e.g., from a file picker or Content Provider), you'll need to convert it to a real file path first. Use this helper method to resolve the path from the content URI:
private String getRealFilePathFromContentUri(Context context, Uri contentUri) { String filePath = null; String[] projection = {MediaStore.Files.FileColumns.DATA}; Cursor cursor = context.getContentResolver().query(contentUri, projection, null, null, null); if (cursor != null) { int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DATA); cursor.moveToFirst(); filePath = cursor.getString(columnIndex); cursor.close(); } return filePath; }
Then use the resolved path to create a File and pass it to Firebase Storage:
Uri contentUri = ...; // Your existing content:// URI String realPath = getRealFilePathFromContentUri(context, contentUri); if (realPath != null) { File localFile = new File(realPath); storageRef.getFile(localFile) // Add success/failure listeners here } else { // Handle case where content URI couldn't be resolved to a file path // This might happen with scoped storage or private content providers }
Important Notes for Android 10+
On Android 10 (API 29) and above, scoped storage restricts direct access to file paths. If the content:// URI points to a file in an app's private directory or a system-managed media file, the helper method above might return null. In this case, use ContentResolver.openInputStream() to read the content and write it to a temporary file in your app's private storage first, then pass that temporary file to Firebase's getFile().
内容的提问来源于stack exchange,提问作者Andrew Lam

