콘솔로 이동

Android에서 파일 다운로드

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

참조 만들기

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

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

자바
Android

// Create a storage reference from our app
StorageReference storageRef = storage.getReference();

// Create a reference with an initial file path and name
StorageReference pathReference = storageRef.child("images/stars.jpg");

// Create a reference to a file from a Google Cloud Storage URI
StorageReference gsReference = storage.getReferenceFromUrl("gs://bucket/images/stars.jpg");

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

Kotlin
Android

// Create a storage reference from our app
val storageRef = storage.reference

// Create a reference with an initial file path and name
val pathReference = storageRef.child("images/stars.jpg")

// Create a reference to a file from a Google Cloud Storage URI
val gsReference = storage.getReferenceFromUrl("gs://bucket/images/stars.jpg")

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

파일 다운로드

참조를 만들었으면 getBytes() 또는 getStream()을 호출하여 Cloud Storage에서 파일을 다운로드할 수 있습니다. 다른 라이브러리로 파일을 다운로드하려는 경우 getDownloadUrl()로 다운로드 URL을 가져올 수 있습니다.

메모리에 다운로드

getBytes() 메소드로 파일을 byte[]에 다운로드합니다. 이는 파일을 다운로드하는 가장 쉬운 방법이지만, 메모리에 전체 파일 내용을 로드해야 합니다. 따라서 앱의 가용 메모리보다 큰 파일을 요청하면 앱이 다운됩니다. 메모리 문제를 방지하기 위해 getBytes()는 다운로드할 최대 바이트 수를 취합니다. 최대 크기를 앱에서 처리할 수 있는 크기로 설정하거나 다른 다운로드 방법을 사용하세요.

자바
Android

StorageReference islandRef = storageRef.child("images/island.jpg");

final long ONE_MEGABYTE = 1024 * 1024;
islandRef.getBytes(ONE_MEGABYTE).addOnSuccessListener(new OnSuccessListener<byte[]>() {
    @Override
    public void onSuccess(byte[] bytes) {
        // Data for "images/island.jpg" is returns, use this as needed
    }
}).addOnFailureListener(new OnFailureListener() {
    @Override
    public void onFailure(@NonNull Exception exception) {
        // Handle any errors
    }
});

Kotlin
Android

var islandRef = storageRef.child("images/island.jpg")

val ONE_MEGABYTE: Long = 1024 * 1024
islandRef.getBytes(ONE_MEGABYTE).addOnSuccessListener {
    // Data for "images/island.jpg" is returned, use this as needed
}.addOnFailureListener {
    // Handle any errors
}

로컬 파일로 다운로드

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

자바
Android

islandRef = storageRef.child("images/island.jpg");

File localFile = File.createTempFile("images", "jpg");

islandRef.getFile(localFile).addOnSuccessListener(new OnSuccessListener<FileDownloadTask.TaskSnapshot>() {
    @Override
    public void onSuccess(FileDownloadTask.TaskSnapshot taskSnapshot) {
        // Local temp file has been created
    }
}).addOnFailureListener(new OnFailureListener() {
    @Override
    public void onFailure(@NonNull Exception exception) {
        // Handle any errors
    }
});

Kotlin
Android

islandRef = storageRef.child("images/island.jpg")

val localFile = File.createTempFile("images", "jpg")

islandRef.getFile(localFile).addOnSuccessListener {
    // Local temp file has been created
}.addOnFailureListener {
    // Handle any errors
}

다운로드를 직접 관리하는 방법은 다운로드 관리를 참조하세요.

URL을 통해 데이터 다운로드

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

자바
Android

storageRef.child("users/me/profile.png").getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
    @Override
    public void onSuccess(Uri uri) {
        // Got the download URL for 'users/me/profile.png'
    }
}).addOnFailureListener(new OnFailureListener() {
    @Override
    public void onFailure(@NonNull Exception exception) {
        // Handle any errors
    }
});

Kotlin
Android

storageRef.child("users/me/profile.png").downloadUrl.addOnSuccessListener {
    // Got the download URL for 'users/me/profile.png'
}.addOnFailureListener {
    // Handle any errors
}

FirebaseUI로 이미지 다운로드

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

우선 app/build.gradle에 FirebaseUI를 추가합니다.

dependencies {
    // FirebaseUI Storage only
    implementation 'com.firebaseui:firebase-ui-storage:4.3.1'
}

이제 저장소의 이미지를 ImageView에 직접 로드할 수 있습니다.

자바
Android

// Reference to an image file in Cloud Storage
StorageReference storageReference = FirebaseStorage.getInstance().getReference();

// ImageView in your Activity
ImageView imageView = findViewById(R.id.imageView);

// Download directly from StorageReference using Glide
// (See MyAppGlideModule for Loader registration)
GlideApp.with(this /* context */)
        .load(storageReference)
        .into(imageView);

Kotlin
Android

// Reference to an image file in Cloud Storage
val storageReference = FirebaseStorage.getInstance().reference

// ImageView in your Activity
val imageView = findViewById<ImageView>(R.id.imageView)

// Download directly from StorageReference using Glide
// (See MyAppGlideModule for Loader registration)
GlideApp.with(this /* context */)
        .load(storageReference)
        .into(imageView)

활동 주기 변화 처리

대화상자 표시, 화면 회전 등으로 인해 활동 주기가 변화해도 다운로드는 백그라운드에서 계속됩니다. 연결된 리스너도 연결된 채로 유지되므로 이 때문에 활동이 중지된 후 리스너가 호출되면 예기치 않은 결과가 나타날 수 있습니다.

활동 범위와 함께 리스너를 등록하면 활동이 중지될 때 리스너가 자동으로 등록 취소되므로 문제가 해결됩니다. 그런 다음 활동이 다시 시작될 때 getActiveDownloadTasks 메소드를 사용하여 여전히 실행 중이거나 최근에 완료된 다운로드 작업을 가져올 수 있습니다.

아래 예에서는 이 방법과 함께 사용된 저장소 참조 경로를 유지하는 방법을 보여 줍니다.

자바
Android

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

    // If there's a download in progress, save the reference so you can query it later
    if (mStorageRef != null) {
        outState.putString("reference", mStorageRef.toString());
    }
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);

    // If there was a download in progress, get its reference and create a new StorageReference
    final String stringRef = savedInstanceState.getString("reference");
    if (stringRef == null) {
        return;
    }
    mStorageRef = FirebaseStorage.getInstance().getReferenceFromUrl(stringRef);

    // Find all DownloadTasks under this StorageReference (in this example, there should be one)
    List<FileDownloadTask> tasks = mStorageRef.getActiveDownloadTasks();
    if (tasks.size() > 0) {
        // Get the task monitoring the download
        FileDownloadTask task = tasks.get(0);

        // Add new listeners to the task using an Activity scope
        task.addOnSuccessListener(this, new OnSuccessListener<FileDownloadTask.TaskSnapshot>() {
            @Override
            public void onSuccess(FileDownloadTask.TaskSnapshot state) {
                // Success!
                // ...
            }
        });
    }
}

Kotlin
Android

override fun onSaveInstanceState(outState: Bundle) {
    super.onSaveInstanceState(outState)

    // If there's a download in progress, save the reference so you can query it later
    storageRef?.let {
        outState.putString("reference", it.toString())
    }
}

override fun onRestoreInstanceState(savedInstanceState: Bundle) {
    super.onRestoreInstanceState(savedInstanceState)

    // If there was a download in progress, get its reference and create a new StorageReference
    val stringRef = savedInstanceState.getString("reference") ?: return

    storageRef = FirebaseStorage.getInstance().getReferenceFromUrl(stringRef)

    // Find all DownloadTasks under this StorageReference (in this example, there should be one)
    val tasks = storageRef?.activeDownloadTasks

    tasks?.size?.let { it ->
        if (it > 0) {
            // Get the task monitoring the download
            val task = tasks[0]

            // Add new listeners to the task using an Activity scope
            task.addOnSuccessListener(this) {
                // Success!
                // ...
            }
        }
    }
}

오류 처리

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

전체 예

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

자바
Android

storageRef.child("users/me/profile.png").getBytes(Long.MAX_VALUE).addOnSuccessListener(new OnSuccessListener<byte[]>() {
    @Override
    public void onSuccess(byte[] bytes) {
        // Use the bytes to display the image
    }
}).addOnFailureListener(new OnFailureListener() {
    @Override
    public void onFailure(@NonNull Exception exception) {
        // Handle any errors
    }
});

Kotlin
Android

storageRef.child("users/me/profile.png").getBytes(Long.MAX_VALUE).addOnSuccessListener {
    // Use the bytes to display the image
}.addOnFailureListener {
    // Handle any errors
}

Cloud Storage에 저장된 파일의 메타데이터를 가져와서 업데이트할 수도 있습니다.