在 Android 上使用 Cloud Storage 下載文件

Cloud Storage for Firebase 讓您可以快速輕鬆地從 Firebase 提供和管理的Cloud Storage 儲存桶下載檔案。

建立參考

若要下載文件,請先建立要下載的文件的 Cloud Storage 引用

您可以透過將子路徑附加到 Cloud Storage 儲存桶的根來建立引用,也可以從引用 Cloud Storage 中物件的現有gs://https:// URL 建立參考。

Kotlin+KTX

// Create a storage reference from our app
val storageRef = storage.reference

// Create a reference with an initial file path and name
val pathReference = storageRef.child("images/stars.jpg")

// Create a reference to a file from a Google Cloud Storage URI
val gsReference = storage.getReferenceFromUrl("gs://bucket/images/stars.jpg")

// Create a reference from an HTTPS URL
// Note that in the URL, characters are URL escaped!
val httpsReference = storage.getReferenceFromUrl(
    "https://firebasestorage.googleapis.com/b/bucket/o/images%20stars.jpg",
)

Java

// Create a storage reference from our app
StorageReference storageRef = storage.getReference();

// Create a reference with an initial file path and name
StorageReference pathReference = storageRef.child("images/stars.jpg");

// Create a reference to a file from a Google Cloud Storage URI
StorageReference gsReference = storage.getReferenceFromUrl("gs://bucket/images/stars.jpg");

// Create a reference from an HTTPS URL
// Note that in the URL, characters are URL escaped!
StorageReference httpsReference = storage.getReferenceFromUrl("https://firebasestorage.googleapis.com/b/bucket/o/images%20stars.jpg");

下載文件

取得參考後,您可以透過呼叫getBytes()getStream()從 Cloud Storage 下載檔案。如果您喜歡使用其他庫下載文件,可以使用getDownloadUrl()來取得下載 URL。

下載到記憶體中

使用getBytes()方法將檔案下載到byte[] 。這是下載檔案的最簡單方法,但它必須將檔案的全部內容載入到記憶體中。如果您要求的檔案大於應用程式的可用內存,您的應用程式將崩潰。為了防止記憶體問題, getBytes()需要下載最大位元組數。將最大大小設為您知道應用程式可以處理的大小,或使用其他下載方法。

Kotlin+KTX

var islandRef = storageRef.child("images/island.jpg")

val ONE_MEGABYTE: Long = 1024 * 1024
islandRef.getBytes(ONE_MEGABYTE).addOnSuccessListener {
    // Data for "images/island.jpg" is returned, use this as needed
}.addOnFailureListener {
    // Handle any errors
}

Java

StorageReference islandRef = storageRef.child("images/island.jpg");

final long ONE_MEGABYTE = 1024 * 1024;
islandRef.getBytes(ONE_MEGABYTE).addOnSuccessListener(new OnSuccessListener<byte[]>() {
    @Override
    public void onSuccess(byte[] bytes) {
        // Data for "images/island.jpg" is returns, use this as needed
    }
}).addOnFailureListener(new OnFailureListener() {
    @Override
    public void onFailure(@NonNull Exception exception) {
        // Handle any errors
    }
});

下載到本地文件

getFile()方法將檔案直接下載到本機。如果您的使用者希望在離線狀態下存取該文件或在其他應用程式中共用該文件,請使用此選項。 getFile()傳回一個DownloadTask ,您可以使用它來管理下載並監控下載狀態。

Kotlin+KTX

islandRef = storageRef.child("images/island.jpg")

val localFile = File.createTempFile("images", "jpg")

islandRef.getFile(localFile).addOnSuccessListener {
    // Local temp file has been created
}.addOnFailureListener {
    // Handle any errors
}

Java

islandRef = storageRef.child("images/island.jpg");

File localFile = File.createTempFile("images", "jpg");

islandRef.getFile(localFile).addOnSuccessListener(new OnSuccessListener<FileDownloadTask.TaskSnapshot>() {
    @Override
    public void onSuccess(FileDownloadTask.TaskSnapshot taskSnapshot) {
        // Local temp file has been created
    }
}).addOnFailureListener(new OnFailureListener() {
    @Override
    public void onFailure(@NonNull Exception exception) {
        // Handle any errors
    }
});

如果您想主動管理下載,請參閱管理下載以了解更多資訊。

透過 URL 下載數據

如果您已經擁有基於 URL 的下載基礎架構,或者只是想要共用 URL,則可以透過呼叫 Cloud Storage 參考上的getDownloadUrl()方法來取得檔案的下載 URL。

Kotlin+KTX

storageRef.child("users/me/profile.png").downloadUrl.addOnSuccessListener {
    // Got the download URL for 'users/me/profile.png'
}.addOnFailureListener {
    // Handle any errors
}

Java

storageRef.child("users/me/profile.png").getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
    @Override
    public void onSuccess(Uri uri) {
        // Got the download URL for 'users/me/profile.png'
    }
}).addOnFailureListener(new OnFailureListener() {
    @Override
    public void onFailure(@NonNull Exception exception) {
        // Handle any errors
    }
});

使用 FirebaseUI 下載映像

FirebaseUI提供簡單、可自訂且可用於生產的本機行動綁定,以消除樣板程式碼並推廣 Google 最佳實踐。使用 FirebaseUI,您可以透過與Glide的整合快速輕鬆地從雲端儲存下載、快取和顯示圖像。

首先,將 FirebaseUI 新增至您的app/build.gradle

dependencies {
    // FirebaseUI Storage only
    implementation 'com.firebaseui:firebase-ui-storage:7.2.0'
}

然後,您可以將映像直接從 Cloud Storage 載入到ImageView中:

Kotlin+KTX

// Reference to an image file in Cloud Storage
val storageReference = Firebase.storage.reference

// ImageView in your Activity
val imageView = findViewById<ImageView>(R.id.imageView)

// Download directly from StorageReference using Glide
// (See MyAppGlideModule for Loader registration)
Glide.with(context)
    .load(storageReference)
    .into(imageView)

Java

// Reference to an image file in Cloud Storage
StorageReference storageReference = FirebaseStorage.getInstance().getReference();

// ImageView in your Activity
ImageView imageView = findViewById(R.id.imageView);

// Download directly from StorageReference using Glide
// (See MyAppGlideModule for Loader registration)
Glide.with(context)
        .load(storageReference)
        .into(imageView);

處理活動生命週期變更

即使活動生命週期發生變化(例如顯示對話方塊或旋轉螢幕),下載也會在背景繼續進行。您附加的任何聽眾也將保持附加狀態。如果他們在活動停止後被調用,這可能會導致意外結果。

您可以透過使用活動範圍訂閱偵聽器來解決此問題,以便在活動停止時自動取消註冊它們。然後,在 Activity 重新啟動時使用getActiveDownloadTasks方法來取得仍在執行或最近完成的下載任務。

下面的範例示範了這一點,並展示如何保留所使用的儲存引用路徑。

Kotlin+KTX

override fun onSaveInstanceState(outState: Bundle) {
    super.onSaveInstanceState(outState)

    // If there's a download in progress, save the reference so you can query it later
    outState.putString("reference", storageRef.toString())
}

override fun onRestoreInstanceState(savedInstanceState: Bundle) {
    super.onRestoreInstanceState(savedInstanceState)

    // If there was a download in progress, get its reference and create a new StorageReference
    val stringRef = savedInstanceState.getString("reference") ?: return

    storageRef = Firebase.storage.getReferenceFromUrl(stringRef)

    // Find all DownloadTasks under this StorageReference (in this example, there should be one)
    val tasks = storageRef.activeDownloadTasks

    if (tasks.size > 0) {
        // Get the task monitoring the download
        val task = tasks[0]

        // Add new listeners to the task using an Activity scope
        task.addOnSuccessListener(this) {
            // Success!
            // ...
        }
    }
}

Java

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

    // If there's a download in progress, save the reference so you can query it later
    if (mStorageRef != null) {
        outState.putString("reference", mStorageRef.toString());
    }
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);

    // If there was a download in progress, get its reference and create a new StorageReference
    final String stringRef = savedInstanceState.getString("reference");
    if (stringRef == null) {
        return;
    }
    mStorageRef = FirebaseStorage.getInstance().getReferenceFromUrl(stringRef);

    // Find all DownloadTasks under this StorageReference (in this example, there should be one)
    List<FileDownloadTask> tasks = mStorageRef.getActiveDownloadTasks();
    if (tasks.size() > 0) {
        // Get the task monitoring the download
        FileDownloadTask task = tasks.get(0);

        // Add new listeners to the task using an Activity scope
        task.addOnSuccessListener(this, new OnSuccessListener<FileDownloadTask.TaskSnapshot>() {
            @Override
            public void onSuccess(FileDownloadTask.TaskSnapshot state) {
                // Success!
                // ...
            }
        });
    }
}

處理錯誤

下載時出現錯誤的原因有很多,包括文件不存在或使用者沒有存取所需文件的權限。有關錯誤的更多資訊可以在文件的處理錯誤部分找到。

完整範例

下面顯示了帶有錯誤處理的下載的完整範例:

Kotlin+KTX

storageRef.child("users/me/profile.png").getBytes(Long.MAX_VALUE).addOnSuccessListener {
    // Use the bytes to display the image
}.addOnFailureListener {
    // Handle any errors
}

Java

storageRef.child("users/me/profile.png").getBytes(Long.MAX_VALUE).addOnSuccessListener(new OnSuccessListener<byte[]>() {
    @Override
    public void onSuccess(byte[] bytes) {
        // Use the bytes to display the image
    }
}).addOnFailureListener(new OnFailureListener() {
    @Override
    public void onFailure(@NonNull Exception exception) {
        // Handle any errors
    }
});

您也可以取得和更新儲存在 Cloud Storage 中的檔案的元資料