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) {
  // ...
}

ダウンロード URL を取得する

ファイルをアップロードした後、ReferencegetDownloadUrl() メソッドを呼び出して、ファイルをダウンロードするための URL を取得できます。

await mountainsRef.getDownloadURL();

ファイル メタデータを追加する

ファイルをアップロードするときにメタデータを含めることもできます。このメタデータには、contentType(一般的に MIME タイプと呼ばれます)などの標準的なファイル メタデータのプロパティが含まれます。putFile() メソッドでは File 拡張子から MIME タイプが自動的に推測されますが、メタデータに contentType を指定することで、自動検出されるタイプをオーバーライドできます。contentType が指定されず、Cloud Storage がファイル拡張子からデフォルトのコンテンツ タイプを自動的に推測することもできない場合は、application/octet-stream が使用されます。ファイル メタデータを使用するをご覧ください。

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

アップロードを管理する

アップロードを開始するだけでなく、pause()resume()cancel() メソッドを使ってアップロードを一時停止、再開、キャンセルすることもできます。イベントを一時停止するとステータスが pause に変わり、イベントを再開するとステータスが progress に変わります。アップロードをキャンセルするとアップロードが失敗し、アップロードがキャンセルされたことを示すエラーが返されます。

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 からファイルをダウンロードする方法を学習しましょう。