Flutter에서 Cloud Storage로 파일 업로드

Firebase용 Cloud Storage를 사용하면 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() 메서드를 사용하여 데이터를 원시, base64, base64url 또는 data_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 가져오기

파일을 업로드한 후 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에서 다운로드하는 방법을 알아보세요.