透過 Apple 平台上的 Cloud Storage 上傳檔案

Cloud Storage for Firebase 可讓您輕鬆快速地將檔案上傳至 提供 Cloud Storage 值區 並由 Firebase 管理

可建立參照

如要上傳檔案,請先 建立 Cloud Storage 參考資料 拖曳到 Cloud Storage 中要上傳檔案的位置。

您可以在 Cloud Storage 值區:

Swift

// Create a root reference
let storageRef = storage.reference()

// Create a reference to "mountains.jpg"
let mountainsRef = storageRef.child("mountains.jpg")

// Create a reference to 'images/mountains.jpg'
let mountainImagesRef = storageRef.child("images/mountains.jpg")

// While the file names are the same, the references point to different files
mountainsRef.name == mountainImagesRef.name            // true
mountainsRef.fullPath == mountainImagesRef.fullPath    // false
    

Objective-C

// Create a root reference
FIRStorageReference *storageRef = [storage reference];

// Create a reference to "mountains.jpg"
FIRStorageReference *mountainsRef = [storageRef child:@"mountains.jpg"];

// Create a reference to 'images/mountains.jpg'
FIRStorageReference *mountainImagesRef = [storageRef child:@"images/mountains.jpg"];

// While the file names are the same, the references point to different files
[mountainsRef.name isEqualToString:mountainImagesRef.name];         // true
[mountainsRef.fullPath isEqualToString:mountainImagesRef.fullPath]; // false
  

您無法上傳任何參照 Cloud Storage 值區您的參照必須指向子網址。

上傳檔案

取得參考資訊後,您可以將檔案上傳至 Cloud Storage 有兩種做法:

  1. 從記憶體中的資料上傳
  2. 從代表裝置上檔案的網址上傳

從記憶體中的資料上傳

putData:metadata:completion: 方法是上傳檔案最簡單的方法 至 Cloud Storage「putData:metadata:completion:」會擷取 NSData 物件並傳回 FIRStorageUploadTask,可用於管理 上傳並監控其狀態

Swift

// Data in memory
let data = Data()

// Create a reference to the file you want to upload
let riversRef = storageRef.child("images/rivers.jpg")

// Upload the file to the path "images/rivers.jpg"
let uploadTask = riversRef.putData(data, metadata: nil) { (metadata, error) in
  guard let metadata = metadata else {
    // Uh-oh, an error occurred!
    return
  }
  // Metadata contains file metadata such as size, content-type.
  let size = metadata.size
  // You can also access to download URL after upload.
  riversRef.downloadURL { (url, error) in
    guard let downloadURL = url else {
      // Uh-oh, an error occurred!
      return
    }
  }
}
    

Objective-C

// Data in memory
NSData *data = [NSData dataWithContentsOfFile:@"rivers.jpg"];

// Create a reference to the file you want to upload
FIRStorageReference *riversRef = [storageRef child:@"images/rivers.jpg"];

// Upload the file to the path "images/rivers.jpg"
FIRStorageUploadTask *uploadTask = [riversRef putData:data
                                             metadata:nil
                                           completion:^(FIRStorageMetadata *metadata,
                                                        NSError *error) {
  if (error != nil) {
    // Uh-oh, an error occurred!
  } else {
    // Metadata contains file metadata such as size, content-type, and download URL.
    int size = metadata.size;
    // You can also access to download URL after upload.
    [riversRef downloadURLWithCompletion:^(NSURL * _Nullable URL, NSError * _Nullable error) {
      if (error != nil) {
        // Uh-oh, an error occurred!
      } else {
        NSURL *downloadURL = URL;
      }
    }];
  }
}];
  

從本機檔案上傳

您可以上傳裝置上的本機檔案,例如相片和影片的本機檔案 相機使用 putFile:metadata:completion: 方法。 putFile:metadata:completion: 會擷取 NSURL 並傳回 FIRStorageUploadTask,可用於管理上傳內容及監控其內容 狀態。

Swift

// File located on disk
let localFile = URL(string: "path/to/image")!

// Create a reference to the file you want to upload
let riversRef = storageRef.child("images/rivers.jpg")

// Upload the file to the path "images/rivers.jpg"
let uploadTask = riversRef.putFile(from: localFile, metadata: nil) { metadata, error in
  guard let metadata = metadata else {
    // Uh-oh, an error occurred!
    return
  }
  // Metadata contains file metadata such as size, content-type.
  let size = metadata.size
  // You can also access to download URL after upload.
  riversRef.downloadURL { (url, error) in
    guard let downloadURL = url else {
      // Uh-oh, an error occurred!
      return
    }
  }
}
    

Objective-C

// File located on disk
NSURL *localFile = [NSURL URLWithString:@"path/to/image"];

// Create a reference to the file you want to upload
FIRStorageReference *riversRef = [storageRef child:@"images/rivers.jpg"];

// Upload the file to the path "images/rivers.jpg"
FIRStorageUploadTask *uploadTask = [riversRef putFile:localFile metadata:nil completion:^(FIRStorageMetadata *metadata, NSError *error) {
  if (error != nil) {
    // Uh-oh, an error occurred!
  } else {
    // Metadata contains file metadata such as size, content-type, and download URL.
    int size = metadata.size;
    // You can also access to download URL after upload.
    [riversRef downloadURLWithCompletion:^(NSURL * _Nullable URL, NSError * _Nullable error) {
      if (error != nil) {
        // Uh-oh, an error occurred!
      } else {
        NSURL *downloadURL = URL;
      }
    }];
  }
}];
  

如要主動管理上傳內容,可以使用 putData:putFile: 方法,觀察上傳工作,而不要使用 設定完成。詳情請參閱「管理上傳項目」一文 可能不準確或不適當

新增檔案中繼資料

您也可以在上傳檔案時加入中繼資料。 這項中繼資料包含一般檔案中繼資料屬性,例如 namesize、 和 contentType (通常稱為 MIME 類型)。putFile: 方法 會自動從 NSURL 副檔名推斷內容類型,但 只要在contentType 中繼資料。如果未提供 contentType 和 Cloud Storage 無法從檔案副檔名推斷預設值,Cloud Storage 會使用 application/octet-stream。詳情請參閱 使用檔案中繼資料 一節,進一步瞭解檔案中繼資料。

Swift

// Create storage reference
let mountainsRef = storageRef.child("images/mountains.jpg")

// Create file metadata including the content type
let metadata = StorageMetadata()
metadata.contentType = "image/jpeg"

// Upload data and metadata
mountainsRef.putData(data, metadata: metadata)

// Upload file and metadata
mountainsRef.putFile(from: localFile, metadata: metadata)
    

Objective-C

// Create storage reference
FIRStorageReference *mountainsRef = [storageRef child:@"images/mountains.jpg"];

// Create file metadata including the content type
FIRStorageMetadata *metadata = [[FIRStorageMetadata alloc] init];
metadata.contentType = @"image/jpeg";

// Upload data and metadata
FIRStorageUploadTask *uploadTask = [mountainsRef putData:data metadata:metadata];

// Upload file and metadata
uploadTask = [mountainsRef putFile:localFile metadata:metadata];
  

管理上傳項目

除了開始上傳之外,您還可以使用 pauseresumecancel 方法。這些方法會引發 pauseresumecancel 事件。取消上傳會導致上傳失敗 出現錯誤訊息,表示上傳作業已取消。

Swift

// Start uploading a file
let uploadTask = storageRef.putFile(from: localFile)

// Pause the upload
uploadTask.pause()

// Resume the upload
uploadTask.resume()

// Cancel the upload
uploadTask.cancel()
    

Objective-C

// Start uploading a file
FIRStorageUploadTask *uploadTask = [storageRef putFile:localFile];

// Pause the upload
[uploadTask pause];

// Resume the upload
[uploadTask resume];

// Cancel the upload
[uploadTask cancel];
  

監控上傳進度

您可以將觀察器附加至 FIRStorageUploadTask,以便監控 上傳進度。新增觀察器會傳回 FIRStorageHandle 可用來移除觀察器

Swift

// Add a progress observer to an upload task
let observer = uploadTask.observe(.progress) { snapshot in
  // A progress event occured
}
    

Objective-C

// Add a progress observer to an upload task
FIRStorageHandle observer = [uploadTask 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 上傳期間含有正在上傳的中繼資料。在 FIRTaskStatusSuccess 事件之後,包含上傳檔案的中繼資料。
task FIRStorageUploadTask 這是一項工作的快照,可以用來管理 (pauseresumecancel) 工作。
reference FIRStorageReference 這項工作的參照。

您也可以依狀態移除個別觀察器,也可以移除 全部都沒問題

Swift

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

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

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

// Remove all observers
uploadTask.removeAllObservers()
    

Objective-C

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

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

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

// Remove all observers
[uploadTask removeAllObservers];
  

為避免記憶體流失,所有觀察器都會在 出現FIRStorageTaskStatusSuccessFIRStorageTaskStatusFailure

處理錯誤

導致上傳發生錯誤的原因有很多種,包括 本機檔案不存在,或使用者無權上傳 指定要上傳的檔案如要進一步瞭解錯誤,請參閱 處理錯誤 一節。

完整範例

含有進度監控和錯誤處理機制的完整上傳示例 如下所示:

Swift

// Local file you want to upload
let localFile = URL(string: "path/to/image")!

// Create the file metadata
let metadata = StorageMetadata()
metadata.contentType = "image/jpeg"

// Upload file and metadata to the object 'images/mountains.jpg'
let uploadTask = storageRef.putFile(from: localFile, metadata: metadata)

// Listen for state changes, errors, and completion of the upload.
uploadTask.observe(.resume) { snapshot in
  // Upload resumed, also fires when the upload starts
}

uploadTask.observe(.pause) { snapshot in
  // Upload paused
}

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

uploadTask.observe(.success) { snapshot in
  // Upload completed successfully
}

uploadTask.observe(.failure) { snapshot in
  if let error = snapshot.error as? NSError {
    switch (StorageErrorCode(rawValue: error.code)!) {
    case .objectNotFound:
      // File doesn't exist
      break
    case .unauthorized:
      // User doesn't have permission to access file
      break
    case .cancelled:
      // User canceled the upload
      break

    /* ... */

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

Objective-C

// Local file you want to upload
NSURL *localFile = [NSURL URLWithString:@"path/to/image"];

// Create the file metadata
FIRStorageMetadata *metadata = [[FIRStorageMetadata alloc] init];
metadata.contentType = @"image/jpeg";

// Upload file and metadata to the object 'images/mountains.jpg'
FIRStorageUploadTask *uploadTask = [storageRef putFile:localFile metadata:metadata];

// Listen for state changes, errors, and completion of the upload.
[uploadTask observeStatus:FIRStorageTaskStatusResume handler:^(FIRStorageTaskSnapshot *snapshot) {
  // Upload resumed, also fires when the upload starts
}];

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

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

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

// Errors only occur in the "Failure" case
[uploadTask 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 執行