Tải tệp lên bằng Cloud Storage trên Flutter

Cloud Storage cho Firebase cho phép bạn tải tệp lên một bộ chứa Cloud Storage do Firebase cung cấp và quản lý một cách nhanh chóng và dễ dàng.

Tải tệp lên

Để tải tệp lên Cloud Storage, trước tiên, bạn cần tạo một tệp tham chiếu đến đường dẫn đầy đủ của tệp, bao gồm cả tên tệp.

// 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);

Sau khi tạo một tệp đối chiếu thích hợp, bạn sẽ gọi phương thức putFile(), putString() hoặc putData() để tải tệp lên Cloud Storage.

Bạn không thể tải dữ liệu lên có tham chiếu đến thư mục gốc của bộ chứa Cloud Storage. URL tham chiếu của bạn phải trỏ đến một URL con.

Tải lên từ tệp

Để tải một tệp lên, trước tiên, bạn phải lấy đường dẫn tuyệt đối đến vị trí của tệp đó trên thiết bị. Ví dụ: nếu một tệp tồn tại trong thư mục tài liệu của ứng dụng, hãy sử dụng gói path_provider chính thức để tạo đường dẫn tệp và truyền đường dẫn đó đến 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) {
  // ...
}

Tải lên từ một chuỗi

Bạn có thể tải dữ liệu lên dưới dạng chuỗi thô, base64, base64url hoặc data_url được mã hoá bằng phương thức putString(). Ví dụ: để tải một chuỗi văn bản được mã hoá dưới dạng URL dữ liệu lên:

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

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

Tải dữ liệu thô lên

Bạn có thể tải dữ liệu đã nhập cấp thấp hơn lên dưới dạng Uint8List trong những trường hợp không thực tế khi tải chuỗi hoặc File lên. Trong trường hợp này, hãy gọi phương thức putData() bằng dữ liệu của bạn:

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

Lấy URL tải xuống

Sau khi tải tệp lên, bạn có thể lấy URL để tải tệp xuống bằng cách gọi phương thức getDownloadUrl() trên Reference:

await mountainsRef.getDownloadURL();

Thêm siêu dữ liệu tệp

Bạn cũng có thể thêm siêu dữ liệu khi tải tệp lên. Siêu dữ liệu này chứa các thuộc tính siêu dữ liệu tệp thông thường như contentType (thường được gọi là loại MIME). Phương thức putFile() sẽ tự động dự đoán loại MIME từ phần mở rộng File, nhưng bạn có thể ghi đè loại được phát hiện tự động bằng cách chỉ định contentType trong siêu dữ liệu. Nếu bạn không cung cấp contentType và Cloud Storage không thể dự đoán giá trị mặc định từ đuôi tệp, thì Cloud Storage sẽ sử dụng application/octet-stream. Xem phần Sử dụng siêu dữ liệu tệp.

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

Quản lý tải lên

Ngoài việc bắt đầu tải lên, bạn có thể tạm dừng, tiếp tục và huỷ tải lên bằng các phương thức pause(), resume()cancel(). Các sự kiện tạm dừng và tiếp tục sẽ lần lượt gây ra các thay đổi về trạng thái pauseprogress. Việc huỷ tải lên sẽ khiến quá trình tải lên không thành công và có lỗi cho biết rằng quá trình tải lên đã bị huỷ.

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');

Theo dõi tiến trình tải lên

Bạn có thể nghe luồng sự kiện của một tác vụ để xử lý trạng thái thành công, không thành công, tiến trình hoặc tạm dừng trong tác vụ tải lên:

Loại sự kiện Cách sử dụng thông thường
TaskState.running Được phát định kỳ khi dữ liệu được chuyển và có thể được dùng để điền chỉ báo tải lên/tải xuống.
TaskState.paused Được phát bất cứ khi nào việc cần làm bị tạm dừng.
TaskState.success Được phát ra khi tác vụ hoàn tất thành công.
TaskState.canceled Được phát ra bất cứ khi nào tác vụ bị huỷ.
TaskState.error Được phát khi quá trình tải lên không thành công. Điều này có thể xảy ra do hết thời gian chờ mạng, lỗi uỷ quyền hoặc nếu bạn huỷ tác vụ.
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;
  }
});

Lỗi xử lý

Có một số lý do khiến lỗi có thể xảy ra khi tải lên, bao gồm cả việc tệp cục bộ không tồn tại hoặc người dùng không có quyền tải tệp mong muốn lên. Bạn có thể tìm thêm thông tin về lỗi trong phần Xử lý lỗi của tài liệu.

Ví dụ đầy đủ

Dưới đây là ví dụ đầy đủ về một lượt tải lên có tính năng theo dõi tiến trình và xử lý lỗi:

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;
  }
});

Giờ thì bạn đã tải tệp lên, hãy tìm hiểu cách tải tệp xuống từ Cloud Storage.