透過 Apple 平台上的 Cloud Storage 下載檔案

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

可建立參照

如要下載檔案,請先建立 Cloud Storage 參照,指向要下載的檔案。

您可以將子路徑附加至 Cloud Storage 值區的根目錄,藉此建立參照,也可以從現有的 gs://https:// 網址建立參照,以便參照 Cloud Storage 中的物件。

Swift

// Create a reference with an initial file path and name
let pathReference = storage.reference(withPath: "images/stars.jpg")

// Create a reference from a Google Cloud Storage URI
let gsReference = storage.reference(forURL: "gs://<your-firebase-storage-bucket>/images/stars.jpg")

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

Objective-C

// Create a reference with an initial file path and name
FIRStorageReference *pathReference = [storage referenceWithPath:@"images/stars.jpg"];

// Create a reference from a Google Cloud Storage URI
FIRStorageReference *gsReference = [storage referenceForURL:@"gs://<your-firebase-storage-bucket>/images/stars.jpg"];

// Create a reference from an HTTPS URL
// Note that in the URL, characters are URL escaped!
FIRStorageReference *httpsReference = [storage referenceForURL:@"https://firebasestorage.googleapis.com/b/bucket/o/images%20stars.jpg"];
  

下載檔案

取得參照後,您可以透過下列三種方式下載 Cloud Storage 中的檔案:

  1. 下載至記憶體中的 NSData
  2. 下載至代表裝置上檔案的 NSURL
  3. 產生代表檔案的 NSURL

在記憶體中下載

使用 dataWithMaxSize:completion: 方法,將檔案下載至記憶體中的 NSData 物件。這是快速下載檔案最簡單的方法,但必須將檔案的完整內容載入記憶體中。如果您要求的檔案大小超過應用程式可用的記憶體,應用程式就會當機。為避免記憶體問題,請務必將最大大小設為應用程式可處理的大小,或使用其他下載方法。

Swift

// Create a reference to the file you want to download
let islandRef = storageRef.child("images/island.jpg")

// Download in memory with a maximum allowed size of 1MB (1 * 1024 * 1024 bytes)
islandRef.getData(maxSize: 1 * 1024 * 1024) { data, error in
  if let error = error {
    // Uh-oh, an error occurred!
  } else {
    // Data for "images/island.jpg" is returned
    let image = UIImage(data: data!)
  }
}
    

Objective-C

// Create a reference to the file you want to download
FIRStorageReference *islandRef = [storageRef child:@"images/island.jpg"];

// Download in memory with a maximum allowed size of 1MB (1 * 1024 * 1024 bytes)
[islandRef dataWithMaxSize:1 * 1024 * 1024 completion:^(NSData *data, NSError *error){
  if (error != nil) {
    // Uh-oh, an error occurred!
  } else {
    // Data for "images/island.jpg" is returned
    UIImage *islandImage = [UIImage imageWithData:data];
  }
}];
    

下載至本機檔案

writeToFile:completion: 方法會將檔案直接下載到本機裝置。如果使用者想在離線時存取檔案,或在其他應用程式中分享檔案,請使用這個方法。writeToFile:completion: 會傳回 FIRStorageDownloadTask,您可以使用這個值來管理下載作業,並監控上傳作業的狀態。

Swift

// Create a reference to the file you want to download
let islandRef = storageRef.child("images/island.jpg")

// Create local filesystem URL
let localURL = URL(string: "path/to/image")!

// Download to the local filesystem
let downloadTask = islandRef.write(toFile: localURL) { url, error in
  if let error = error {
    // Uh-oh, an error occurred!
  } else {
    // Local file URL for "images/island.jpg" is returned
  }
}
    

Objective-C

// Create a reference to the file you want to download
FIRStorageReference *islandRef = [storageRef child:@"images/island.jpg"];

// Create local filesystem URL
NSURL *localURL = [NSURL URLWithString:@"path/to/image"];

// Download to the local filesystem
FIRStorageDownloadTask *downloadTask = [islandRef writeToFile:localURL completion:^(NSURL *URL, NSError *error){
  if (error != nil) {
    // Uh-oh, an error occurred!
  } else {
    // Local file URL for "images/island.jpg" is returned
  }
}];
    

如果您想主動管理下載作業,可以使用 writeToFile: 方法並觀察下載工作,而非使用完成處理常式。詳情請參閱「管理下載內容」。

產生下載網址

如果您已經有以網址為基礎的下載基礎架構,或是只想取得要分享的網址,您可以在 Cloud Storage 參照上呼叫 downloadURLWithCompletion: 方法,取得檔案的下載網址。

Swift

// Create a reference to the file you want to download
let starsRef = storageRef.child("images/stars.jpg")

// Fetch the download URL
starsRef.downloadURL { url, error in
  if let error = error {
    // Handle any errors
  } else {
    // Get the download URL for 'images/stars.jpg'
  }
}
    

Objective-C

// Create a reference to the file you want to download
FIRStorageReference *starsRef = [storageRef child:@"images/stars.jpg"];

// Fetch the download URL
[starsRef downloadURLWithCompletion:^(NSURL *URL, NSError *error){
  if (error != nil) {
    // Handle any errors
  } else {
    // Get the download URL for 'images/stars.jpg'
  }
}];
    

使用 FirebaseUI 下載圖片

FirebaseUI 提供簡單、可自訂且可用於實際工作環境的原生行動裝置繫結,可消除樣板程式碼並推廣 Google 最佳做法。您可以使用 FirebaseUI,透過與 SDWebImage 整合,快速輕鬆地下載、快取及顯示 Cloud Storage 中的圖片。

首先,請將 FirebaseUI 新增至 Podfile

pod 'FirebaseStorageUI'

接著,您可以直接從 Cloud Storage 將圖片載入 UIImageView

Swift

// Reference to an image file in Firebase Storage
let reference = storageRef.child("images/stars.jpg")

// UIImageView in your ViewController
let imageView: UIImageView = self.imageView

// Placeholder image
let placeholderImage = UIImage(named: "placeholder.jpg")

// Load the image using SDWebImage
imageView.sd_setImage(with: reference, placeholderImage: placeholderImage)
    

Objective-C

// Reference to an image file in Firebase Storage
FIRStorageReference *reference = [storageRef child:@"images/stars.jpg"];

// UIImageView in your ViewController
UIImageView *imageView = self.imageView;

// Placeholder image
UIImage *placeholderImage;

// Load the image using SDWebImage
[imageView sd_setImageWithStorageReference:reference placeholderImage:placeholderImage];
    

管理下載內容

除了開始下載之外,您還可以使用 pauseresumecancel 方法暫停、繼續和取消下載作業。這些方法會觸發可觀察的 pauseresumecancel 事件。

Swift

// Start downloading a file
let downloadTask = storageRef.child("images/mountains.jpg").write(toFile: localFile)

// Pause the download
downloadTask.pause()

// Resume the download
downloadTask.resume()

// Cancel the download
downloadTask.cancel()
    

Objective-C

// Start downloading a file
FIRStorageDownloadTask *downloadTask = [[storageRef child:@"images/mountains.jpg"] writeToFile:localFile];

// Pause the download
[downloadTask pause];

// Resume the download
[downloadTask resume];

// Cancel the download
[downloadTask cancel];
    

監控下載進度

您可以將觀察器附加至 FIRStorageDownloadTask,以便監控下載進度。新增觀察器會傳回 FIRStorageHandle,可用於移除觀察器。

Swift

// Add a progress observer to a download task
let observer = downloadTask.observe(.progress) { snapshot in
  // A progress event occurred
}
    

Objective-C

// Add a progress observer to a download task
FIRStorageHandle observer = [downloadTask observeStatus:FIRStorageTaskStatusProgress
                                                handler:^(FIRStorageTaskSnapshot *snapshot) {
                                                  // A progress event occurred
                                                }];
    

這些觀察器可註冊至 FIRStorageTaskStatus 事件:

`FIRStorageTaskStatus` 事件 常見用途
FIRStorageTaskStatusResume 這個事件會在工作開始或恢復下載時觸發,通常會與 FIRStorageTaskStatusPause 事件一併使用。
FIRStorageTaskStatusProgress 此事件會在任何從 Cloud Storage 下載資料時觸發,並可用於填入下載進度指標。
FIRStorageTaskStatusPause 只要下載作業暫停,就會觸發這項事件,且通常會與 FIRStorageTaskStatusResume 事件搭配使用。
FIRStorageTaskStatusSuccess 下載完成後會觸發這項事件。
FIRStorageTaskStatusFailure 此事件會在下載失敗時觸發。檢查錯誤,找出失敗原因。

事件發生時,系統會傳回 FIRStorageTaskSnapshot 物件。這個快照是事件發生時,對工作不可變動的檢視畫面。這個物件包含下列屬性:

屬性 類型 說明
progress NSProgress 包含下載進度的 NSProgress 物件。
error NSError 下載期間發生的錯誤 (如果有)。
metadata FIRStorageMetadata nil 下載次數。
task FIRStorageDownloadTask 這是工作快照,可用於管理 (pauseresumecancel) 工作。
reference FIRStorageReference 這項工作的參照來源。

您也可以依狀態個別移除觀察者,或是一次移除所有觀察者。

Swift

// Create a task listener handle
let observer = downloadTask.observe(.progress) { snapshot in
// A progress event occurred
}

// Remove an individual observer
downloadTask.removeObserver(withHandle: observer)

// Remove all observers of a particular status
downloadTask.removeAllObservers(for: .progress)

// Remove all observers
downloadTask.removeAllObservers()
    

Objective-C

// Create a task listener handle
FIRStorageHandle observer = [downloadTask observeStatus:FIRStorageTaskStatusProgress
                                                handler:^(FIRStorageTaskSnapshot *snapshot) {
                                                  // A progress event occurred
                                                }];

// Remove an individual observer
[downloadTask removeObserverWithHandle:observer];

// Remove all observers of a particular status
[downloadTask removeAllObserversForStatus:FIRStorageTaskStatusProgress];

// Remove all observers
[downloadTask removeAllObservers];
    

為避免記憶體流失,系統會在 FIRStorageTaskStatusSuccessFIRStorageTaskStatusFailure 發生後移除所有觀察器。

處理錯誤

下載時可能會發生錯誤,原因有很多,包括檔案不存在,或使用者沒有權限存取所需檔案。如要進一步瞭解錯誤,請參閱文件中的「處理錯誤」一節。

完整範例

以下是下載至本機檔案並處理錯誤的完整範例:

Swift

// Create a reference to the file we want to download
let starsRef = storageRef.child("images/stars.jpg")

// Start the download (in this case writing to a file)
let downloadTask = storageRef.write(toFile: localURL)

// Observe changes in status
downloadTask.observe(.resume) { snapshot in
  // Download resumed, also fires when the download starts
}

downloadTask.observe(.pause) { snapshot in
  // Download paused
}

downloadTask.observe(.progress) { snapshot in
  // Download reported progress
  let percentComplete = 100.0 * Double(snapshot.progress!.completedUnitCount)
    / Double(snapshot.progress!.totalUnitCount)
}

downloadTask.observe(.success) { snapshot in
  // Download completed successfully
}

// Errors only occur in the "Failure" case
downloadTask.observe(.failure) { snapshot in
  guard let errorCode = (snapshot.error as? NSError)?.code else {
    return
  }
  guard let error = StorageErrorCode(rawValue: errorCode) else {
    return
  }
  switch (error) {
  case .objectNotFound:
    // File doesn't exist
    break
  case .unauthorized:
    // User doesn't have permission to access file
    break
  case .cancelled:
    // User cancelled the download
    break

  /* ... */

  case .unknown:
    // Unknown error occurred, inspect the server response
    break
  default:
    // Another error occurred. This is a good place to retry the download.
    break
  }
}
    

Objective-C

// Create a reference to the file we want to download
FIRStorageReference *starsRef = [storageRef child:@"images/stars.jpg"];

// Start the download (in this case writing to a file)
FIRStorageDownloadTask *downloadTask = [storageRef writeToFile:localURL];

// Observe changes in status
[downloadTask observeStatus:FIRStorageTaskStatusResume handler:^(FIRStorageTaskSnapshot *snapshot) {
  // Download resumed, also fires when the download starts
}];

[downloadTask observeStatus:FIRStorageTaskStatusPause handler:^(FIRStorageTaskSnapshot *snapshot) {
  // Download paused
}];

[downloadTask observeStatus:FIRStorageTaskStatusProgress handler:^(FIRStorageTaskSnapshot *snapshot) {
  // Download reported progress
  double percentComplete = 100.0 * (snapshot.progress.completedUnitCount) / (snapshot.progress.totalUnitCount);
}];

[downloadTask observeStatus:FIRStorageTaskStatusSuccess handler:^(FIRStorageTaskSnapshot *snapshot) {
  // Download completed successfully
}];

// Errors only occur in the "Failure" case
[downloadTask observeStatus:FIRStorageTaskStatusFailure handler:^(FIRStorageTaskSnapshot *snapshot) {
  if (snapshot.error != nil) {
    switch (snapshot.error.code) {
      case FIRStorageErrorCodeObjectNotFound:
        // File doesn't exist
        break;

      case FIRStorageErrorCodeUnauthorized:
        // User doesn't have permission to access file
        break;

      case FIRStorageErrorCodeCancelled:
        // User canceled the upload
        break;

      /* ... */

      case FIRStorageErrorCodeUnknown:
        // Unknown error occurred, inspect the server response
        break;
    }
  }
}];
    

您也可以取得及更新中繼資料,適用於儲存在 Cloud Storage 中的檔案。