Apple 플랫폼에서 Cloud Storage로 파일 다운로드

Firebase용 Cloud Storage를 사용하면 Firebase에서 제공하고 관리하는 Cloud Storage 버킷에서 파일을 빠르고 손쉽게 다운로드할 수 있습니다.

참조 만들기

파일을 다운로드하려면 우선 다운로드할 파일을 가리키는 Cloud Storage 참조를 만듭니다.

Cloud Storage 버킷의 루트에 하위 경로를 추가하여 참조를 만들거나 Cloud Storage의 객체를 참조하는 기존 gs:// 또는 https:// URL로 참조를 만들 수 있습니다.

Swift

// Create a reference with an initial file path and name
let pathReference = storage.reference(withPath: "images/stars.jpg")

// Create a reference from a Google Cloud Storage URI
let gsReference = storage.reference(forURL: "gs://<your-firebase-storage-bucket>/images/stars.jpg")

// Create a reference from an HTTPS URL
// Note that in the URL, characters are URL escaped!
let httpsReference = storage.reference(forURL: "https://firebasestorage.googleapis.com/b/bucket/o/images%20stars.jpg")

Objective-C

// Create a reference with an initial file path and name
FIRStorageReference *pathReference = [storage referenceWithPath:@"images/stars.jpg"];

// Create a reference from a Google Cloud Storage URI
FIRStorageReference *gsReference = [storage referenceForURL:@"gs://<your-firebase-storage-bucket>/images/stars.jpg"];

// Create a reference from an HTTPS URL
// Note that in the URL, characters are URL escaped!
FIRStorageReference *httpsReference = [storage referenceForURL:@"https://firebasestorage.googleapis.com/b/bucket/o/images%20stars.jpg"];
  

파일 다운로드

참조가 만들어졌으면 3가지 방법으로 Cloud Storage에서 파일을 다운로드할 수 있습니다.

  1. 메모리에서 NSData로 다운로드
  2. 기기의 파일을 나타내는 NSURL로 다운로드
  3. 온라인 파일을 나타내는 NSURL 생성

메모리에 다운로드

dataWithMaxSize:completion: 메서드를 사용하여 파일을 메모리의 NSData 객체로 다운로드합니다. 이는 파일을 빠르게 다운로드하는 가장 쉬운 방법이지만 메모리에 전체 파일 내용을 로드해야 합니다. 따라서 앱의 가용 메모리보다 큰 파일을 요청하면 앱이 다운됩니다. 메모리 문제를 방지하려면 최대 크기를 앱에서 처리할 수 있는 크기로 설정하거나 다른 다운로드 방법을 사용하세요.

Swift

// Create a reference to the file you want to download
let islandRef = storageRef.child("images/island.jpg")

// Download in memory with a maximum allowed size of 1MB (1 * 1024 * 1024 bytes)
islandRef.getData(maxSize: 1 * 1024 * 1024) { data, error in
  if let error = error {
    // Uh-oh, an error occurred!
  } else {
    // Data for "images/island.jpg" is returned
    let image = UIImage(data: data!)
  }
}
    

Objective-C

// Create a reference to the file you want to download
FIRStorageReference *islandRef = [storageRef child:@"images/island.jpg"];

// Download in memory with a maximum allowed size of 1MB (1 * 1024 * 1024 bytes)
[islandRef dataWithMaxSize:1 * 1024 * 1024 completion:^(NSData *data, NSError *error){
  if (error != nil) {
    // Uh-oh, an error occurred!
  } else {
    // Data for "images/island.jpg" is returned
    UIImage *islandImage = [UIImage imageWithData:data];
  }
}];
    

로컬 파일로 다운로드

writeToFile:completion: 메서드는 파일을 로컬 기기로 직접 다운로드합니다. 사용자가 오프라인 상태에서도 파일에 액세스해야 하거나 다른 앱에서 파일을 공유해야 하는 경우 이 방법을 사용하세요. writeToFile:completion:은 다운로드를 관리하고 다운로드 상태를 모니터링하는 데 사용할 수 있는 FIRStorageDownloadTask를 반환합니다.

Swift

// Create a reference to the file you want to download
let islandRef = storageRef.child("images/island.jpg")

// Create local filesystem URL
let localURL = URL(string: "path/to/image")!

// Download to the local filesystem
let downloadTask = islandRef.write(toFile: localURL) { url, error in
  if let error = error {
    // Uh-oh, an error occurred!
  } else {
    // Local file URL for "images/island.jpg" is returned
  }
}
    

Objective-C

// Create a reference to the file you want to download
FIRStorageReference *islandRef = [storageRef child:@"images/island.jpg"];

// Create local filesystem URL
NSURL *localURL = [NSURL URLWithString:@"path/to/image"];

// Download to the local filesystem
FIRStorageDownloadTask *downloadTask = [islandRef writeToFile:localURL completion:^(NSURL *URL, NSError *error){
  if (error != nil) {
    // Uh-oh, an error occurred!
  } else {
    // Local file URL for "images/island.jpg" is returned
  }
}];
    

다운로드를 적극적으로 관리하려면 완료 핸들러를 사용하는 대신 writeToFile: 메서드를 사용하고 다운로드 작업을 관찰합니다. 자세한 내용은 다운로드 관리를 참조하세요.

다운로드 URL 생성

URL 기반 다운로드 인프라를 갖추고 있거나 단순히 URL을 공유하려는 경우 Cloud Storage 참조에 downloadURLWithCompletion: 메서드를 호출하여 파일의 다운로드 URL을 가져올 수 있습니다.

Swift

// Create a reference to the file you want to download
let starsRef = storageRef.child("images/stars.jpg")

// Fetch the download URL
starsRef.downloadURL { url, error in
  if let error = error {
    // Handle any errors
  } else {
    // Get the download URL for 'images/stars.jpg'
  }
}
    

Objective-C

// Create a reference to the file you want to download
FIRStorageReference *starsRef = [storageRef child:@"images/stars.jpg"];

// Fetch the download URL
[starsRef downloadURLWithCompletion:^(NSURL *URL, NSError *error){
  if (error != nil) {
    // Handle any errors
  } else {
    // Get the download URL for 'images/stars.jpg'
  }
}];
    

FirebaseUI로 이미지 다운로드

FirebaseUI는 단순하고 맞춤설정 가능하고 프로덕션 환경에서 즉시 사용할 수 있는 기본 모바일 바인딩을 제공하며, 이 바인딩을 사용하면 상용구 코드를 제거하고 Google의 권장사항을 도입할 수 있습니다. SDWebImage와 통합해 FirebaseUI를 사용하면 Cloud Storage의 이미지를 빠르고 손쉽게 다운로드하여 캐시에 저장하고 표시할 수 있습니다.

먼저 Podfile에 FirebaseUI를 추가합니다.

pod 'FirebaseStorageUI'

이제 Cloud Storage의 이미지를 UIImageView에 직접 로드할 수 있습니다.

Swift

// Reference to an image file in Firebase Storage
let reference = storageRef.child("images/stars.jpg")

// UIImageView in your ViewController
let imageView: UIImageView = self.imageView

// Placeholder image
let placeholderImage = UIImage(named: "placeholder.jpg")

// Load the image using SDWebImage
imageView.sd_setImage(with: reference, placeholderImage: placeholderImage)
    

Objective-C

// Reference to an image file in Firebase Storage
FIRStorageReference *reference = [storageRef child:@"images/stars.jpg"];

// UIImageView in your ViewController
UIImageView *imageView = self.imageView;

// Placeholder image
UIImage *placeholderImage;

// Load the image using SDWebImage
[imageView sd_setImageWithStorageReference:reference placeholderImage:placeholderImage];
    

다운로드 관리

다운로드 시작 외에도 pause, resume, cancel 메서드를 사용하여 다운로드를 일시중지, 재개, 취소할 수 있습니다. 이러한 메서드는 관찰 가능한 pause, resume, cancel 이벤트를 발생시킵니다.

Swift

// Start downloading a file
let downloadTask = storageRef.child("images/mountains.jpg").write(toFile: localFile)

// Pause the download
downloadTask.pause()

// Resume the download
downloadTask.resume()

// Cancel the download
downloadTask.cancel()
    

Objective-C

// Start downloading a file
FIRStorageDownloadTask *downloadTask = [[storageRef child:@"images/mountains.jpg"] writeToFile:localFile];

// Pause the download
[downloadTask pause];

// Resume the download
[downloadTask resume];

// Cancel the download
[downloadTask cancel];
    

다운로드 진행률 모니터링

다운로드 진행률을 모니터링하려면 FIRStorageDownloadTask에 관찰자를 연결합니다. 관찰자를 추가하면 관찰자를 삭제하는 데 사용할 수 있는 FIRStorageHandle이 반환됩니다.

Swift

// Add a progress observer to a download task
let observer = downloadTask.observe(.progress) { snapshot in
  // A progress event occurred
}
    

Objective-C

// Add a progress observer to a download task
FIRStorageHandle observer = [downloadTask 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 다운로드에 대한 nil입니다.
task FIRStorageDownloadTask 스냅샷 대상 작업으로서 작업을 관리(pause, resume, cancel)하는 데 사용할 수 있습니다.
reference FIRStorageReference 이 작업이 유래된 참조입니다.

관찰자를 하나씩 삭제하거나, 상태별로 삭제하거나, 모두 삭제할 수도 있습니다.

Swift

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

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

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

// Remove all observers
downloadTask.removeAllObservers()
    

Objective-C

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

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

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

// Remove all observers
[downloadTask removeAllObservers];
    

메모리 누수를 방지하기 위해 FIRStorageTaskStatusSuccess 또는 FIRStorageTaskStatusFailure가 발생한 후 모든 관찰자가 삭제됩니다.

오류 처리

다운로드 시 오류가 발생하는 이유는 파일이 없는 경우, 사용자에게 파일 액세스 권한이 없는 경우 등 다양합니다. 오류에 대한 자세한 내용은 문서의 오류 처리 섹션을 참조하세요.

전체 예

다음은 로컬 파일로 다운로드 및 오류 처리에 대한 전체 예입니다.

Swift

// Create a reference to the file we want to download
let starsRef = storageRef.child("images/stars.jpg")

// Start the download (in this case writing to a file)
let downloadTask = storageRef.write(toFile: localURL)

// Observe changes in status
downloadTask.observe(.resume) { snapshot in
  // Download resumed, also fires when the download starts
}

downloadTask.observe(.pause) { snapshot in
  // Download paused
}

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

downloadTask.observe(.success) { snapshot in
  // Download completed successfully
}

// Errors only occur in the "Failure" case
downloadTask.observe(.failure) { snapshot in
  guard let errorCode = (snapshot.error as? NSError)?.code else {
    return
  }
  guard let error = StorageErrorCode(rawValue: errorCode) else {
    return
  }
  switch (error) {
  case .objectNotFound:
    // File doesn't exist
    break
  case .unauthorized:
    // User doesn't have permission to access file
    break
  case .cancelled:
    // User cancelled the download
    break

  /* ... */

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

Objective-C

// Create a reference to the file we want to download
FIRStorageReference *starsRef = [storageRef child:@"images/stars.jpg"];

// Start the download (in this case writing to a file)
FIRStorageDownloadTask *downloadTask = [storageRef writeToFile:localURL];

// Observe changes in status
[downloadTask observeStatus:FIRStorageTaskStatusResume handler:^(FIRStorageTaskSnapshot *snapshot) {
  // Download resumed, also fires when the download starts
}];

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

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

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

// Errors only occur in the "Failure" case
[downloadTask 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에 저장된 파일의 메타데이터를 가져와서 업데이트할 수도 있습니다.