在 Flutter 上使用 Cloud Storage 上傳文件

Cloud Storage for Firebase 讓您可以快速輕鬆地將檔案上傳到由 Firebase 提供和管理的Cloud Storage 儲存桶。

上傳文件

若要將檔案上傳到 Cloud Storage,您首先要建立對檔案完整路徑(包括檔案名稱)的引用。

// Create a storage reference from our app
final storageRef = FirebaseStorage.instance.ref();

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

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

// While the file names are the same, the references point to different files
assert(mountainsRef.name == mountainImagesRef.name);
assert(mountainsRef.fullPath != mountainImagesRef.fullPath);

建立適當的參考後,您可以呼叫putFile()putString()putData()方法將檔案上傳到 Cloud Storage。

您無法上傳引用 Cloud Storage 儲存分區根的資料。您的引用必須指向子 URL。

從文件上傳

要上傳文件,您必須先取得其在裝置上位置的絕對路徑。例如,如果應用程式的文檔目錄中存在文件,請使用官方的path_provider套件產生文件路徑並將其傳遞給putFile()

Directory appDocDir = await getApplicationDocumentsDirectory();
String filePath = '${appDocDir.absolute}/file-to-upload.png';
File file = File(filePath);

try {
  await mountainsRef.putFile(file);
} on firebase_core.FirebaseException catch (e) {
  // ...
}

從字串上傳

您可以使用putString()方法將資料上傳為原始、 base64base64urldata_url編碼字串。例如,要上傳編碼為資料 URL 的文字字串:

String dataUrl = 'data:text/plain;base64,SGVsbG8sIFdvcmxkIQ==';

try {
  await mountainsRef.putString(dataUrl, format: PutStringFormat.dataUrl);
} on FirebaseException catch (e) {
  // ...
}

上傳原始數據

對於上傳字串或File不可行的情況,您可以以Uint8List的形式上傳較低層級的類型資料。在這種情況下,請使用您的資料呼叫putData()方法:

try {
  // Upload raw data.
  await mountainsRef.putData(data);
} on firebase_core.FirebaseException catch (e) {
  // ...
}

取得下載地址

上傳檔案後,您可以透過呼叫Reference上的getDownloadUrl()方法來取得下載檔案的 URL:

await mountainsRef.getDownloadURL();

新增檔案元數據

您也可以在上傳文件時包含元資料。此元資料包含典型的檔案元資料屬性,例如contentType (通常稱為 MIME 類型)。 putFile()方法會自動從File副檔名推斷 MIME 類型,但您可以透過在元資料中指定contentType來覆寫自動偵測到的類型。如果您不提供contentType且 Cloud Storage 無法從檔案副檔名推斷出預設值,Cloud Storage 將使用application/octet-stream 。請參閱使用文件元資料

try {
  await mountainsRef.putFile(file, SettableMetadata(
    contentType: "image/jpeg",
  ));
} on firebase_core.FirebaseException catch (e) {
  // ...
}

管理上傳

除了開始上傳之外,您還可以使用pause()resume()cancel()方法暫停、恢復和取消上傳。暫停和恢復事件分別引發pauseprogress狀態變更。取消上傳會導致上傳失敗,並顯示錯誤,指示上傳已取消。

final task = mountainsRef.putFile(largeFile);

// Pause the upload.
bool paused = await task.pause();
print('paused, $paused');

// Resume the upload.
bool resumed = await task.resume();
print('resumed, $resumed');

// Cancel the upload.
bool canceled = await task.cancel();
print('canceled, $canceled');

監控上傳進度

您可以監聽任務的事件流來處理上傳任務的成功、失敗、進度或暫停:

事件類型典型用法
TaskState.running在資料傳輸時定期發出,可用於填入上傳/下載指示器。
TaskState.paused任務暫停時發出。
TaskState.success任務成功完成時發出。
TaskState.canceled任務取消時發出。
TaskState.error上傳失敗時發出。這可能是由於網路逾時、授權失敗或您取消任務而發生的。
mountainsRef.putFile(file).snapshotEvents.listen((taskSnapshot) {
  switch (taskSnapshot.state) {
    case TaskState.running:
      // ...
      break;
    case TaskState.paused:
      // ...
      break;
    case TaskState.success:
      // ...
      break;
    case TaskState.canceled:
      // ...
      break;
    case TaskState.error:
      // ...
      break;
  }
});

錯誤處理

上傳錯誤的原因有很多,包括本機檔案不存在,或是使用者沒有上傳所需檔案的權限。您可以在文件的處理錯誤部分找到有關錯誤的更多資訊。

完整範例

具有進度監控和錯誤處理功能的上傳的完整範例如下所示:

final appDocDir = await getApplicationDocumentsDirectory();
final filePath = "${appDocDir.absolute}/path/to/mountains.jpg";
final file = File(filePath);

// Create the file metadata
final metadata = SettableMetadata(contentType: "image/jpeg");

// Create a reference to the Firebase Storage bucket
final storageRef = FirebaseStorage.instance.ref();

// Upload file and metadata to the path 'images/mountains.jpg'
final uploadTask = storageRef
    .child("images/path/to/mountains.jpg")
    .putFile(file, metadata);

// Listen for state changes, errors, and completion of the upload.
uploadTask.snapshotEvents.listen((TaskSnapshot taskSnapshot) {
  switch (taskSnapshot.state) {
    case TaskState.running:
      final progress =
          100.0 * (taskSnapshot.bytesTransferred / taskSnapshot.totalBytes);
      print("Upload is $progress% complete.");
      break;
    case TaskState.paused:
      print("Upload is paused.");
      break;
    case TaskState.canceled:
      print("Upload was canceled");
      break;
    case TaskState.error:
      // Handle unsuccessful uploads
      break;
    case TaskState.success:
      // Handle successful uploads on complete
      // ...
      break;
  }
});

現在您已經上傳了文件,讓我們了解如何從 Cloud Storage下載它們