Descargar archivos con Cloud Storage en Android

Cloud Storage para Firebase le permite descargar archivos rápida y fácilmente desde un depósito de Cloud Storage proporcionado y administrado por Firebase.

Crear una referencia

Para descargar un archivo, primero cree una referencia de Cloud Storage para el archivo que desea descargar.

Puedes crear una referencia agregando rutas secundarias a la raíz de tu depósito de Cloud Storage, o puedes crear una referencia a partir de una URL gs:// o https:// existente que haga referencia a un objeto en Cloud Storage.

Kotlin+KTX

// 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",
)

Java

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

Descargar archivos

Una vez que tenga una referencia, puede descargar archivos de Cloud Storage llamando a getBytes() o getStream() . Si prefiere descargar el archivo con otra biblioteca, puede obtener una URL de descarga con getDownloadUrl() .

Descargar en memoria

Descargue el archivo en un byte[] con el método getBytes() . Esta es la forma más sencilla de descargar un archivo, pero debe cargar todo el contenido del archivo en la memoria. Si solicita un archivo más grande que la memoria disponible de su aplicación, su aplicación fallará. Para protegerse contra problemas de memoria, getBytes() necesita una cantidad máxima de bytes para descargar. Establece el tamaño máximo en algo que sepas que tu aplicación puede manejar o utiliza otro método de descarga.

Kotlin+KTX

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
}

Java

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

Descargar a un archivo local

El método getFile() descarga un archivo directamente a un dispositivo local. Úselo si sus usuarios desean tener acceso al archivo sin conexión o compartir el archivo en una aplicación diferente. getFile() devuelve un DownloadTask que puede usar para administrar su descarga y monitorear el estado de la descarga.

Kotlin+KTX

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
}

Java

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

Si desea administrar activamente su descarga, consulte Administrar descargas para obtener más información.

Descargar datos a través de URL

Si ya tiene una infraestructura de descarga basada en URL, o simplemente desea compartir una URL, puede obtener la URL de descarga de un archivo llamando al método getDownloadUrl() en una referencia de Cloud Storage.

Kotlin+KTX

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

Java

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

Descarga de imágenes con FirebaseUI

FirebaseUI proporciona enlaces móviles nativos simples, personalizables y listos para producción para eliminar el código repetitivo y promover las mejores prácticas de Google. Con FirebaseUI puedes descargar, almacenar en caché y mostrar imágenes de forma rápida y sencilla desde Cloud Storage mediante nuestra integración con Glide .

Primero, agrega FirebaseUI a tu app/build.gradle :

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

Luego puedes cargar imágenes directamente desde Cloud Storage en un ImageView :

Kotlin+KTX

// Reference to an image file in Cloud Storage
val storageReference = Firebase.storage.reference

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

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

Java

// 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)
Glide.with(context)
        .load(storageReference)
        .into(imageView);

Manejar los cambios en el ciclo de vida de la actividad

Las descargas continúan en segundo plano incluso después de cambios en el ciclo de vida de la actividad (como presentar un cuadro de diálogo o girar la pantalla). Todos los oyentes que haya adjuntado también permanecerán adjuntos. Esto podría provocar resultados inesperados si reciben una llamada después de que se detiene la actividad.

Puede resolver este problema suscribiendo a sus oyentes con un alcance de actividad para cancelar su registro automáticamente cuando la actividad se detenga. Luego, use el método getActiveDownloadTasks cuando la actividad se reinicie para obtener las tareas de descarga que aún se están ejecutando o se completaron recientemente.

El siguiente ejemplo demuestra esto y también muestra cómo conservar la ruta de referencia de almacenamiento utilizada.

Kotlin+KTX

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

    // If there's a download in progress, save the reference so you can query it later
    outState.putString("reference", storageRef.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 = Firebase.storage.getReferenceFromUrl(stringRef)

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

    if (tasks.size > 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!
            // ...
        }
    }
}

Java

@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!
                // ...
            }
        });
    }
}

Manejar errores

Hay varias razones por las que pueden ocurrir errores durante la descarga, incluido el archivo que no existe o que el usuario no tiene permiso para acceder al archivo deseado. Puede encontrar más información sobre errores en la sección Manejar errores de los documentos.

Ejemplo completo

A continuación se muestra un ejemplo completo de una descarga con manejo de errores:

Kotlin+KTX

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

Java

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

También puede obtener y actualizar metadatos de archivos almacenados en Cloud Storage.