Muestra una lista de archivos con Cloud Storage en Android

Cloud Storage para Firebase te permite mostrar una lista del contenido de tu bucket de Cloud Storage. Los SDK muestran los elementos y los prefijos de los objetos que se encuentran en la referencia de Cloud Storage actual.

Los proyectos que usan la API de List requieren la versión 2 de las reglas de Cloud Storage para Firebase. Si tienes un proyecto de Firebase, sigue los pasos de la Guía sobre reglas de seguridad.

list() usa la API de List de Google Cloud Storage. En Cloud Storage para Firebase, usamos / como delimitador, lo que permite emular la semántica del sistema de archivos. Para permitir un recorrido eficiente de buckets de Cloud Storage jerárquicos y de gran tamaño, la API de List muestra los prefijos y los elementos por separado. Por ejemplo, si subes un archivo /images/uid/file1, ocurrirá lo siguiente:

  • root.child('images').listAll() mostrará /images/uid como un prefijo.
  • root.child('images/uid').listAll() mostrará el archivo como un elemento.

El SDK de Cloud Storage para Firebase no muestra las rutas de acceso a los objetos que contienen dos / consecutivos o que terminan en /. Por ejemplo, considera un bucket que tenga los siguientes objetos:

  • correctPrefix/happyItem
  • wrongPrefix//sadItem
  • lonelyItem/

Las operaciones list que se realicen sobre elementos de este bucket mostrarán los siguientes resultados:

  • Las que se realicen en la raíz mostrarán las referencias a correctPrefix, wrongPrefix y lonelyItem como prefixes.
  • Las que se realicen en correctPrefix/ mostrarán las referencias a correctPrefix/happyItem como items.
  • Las que se realicen en wrongPrefix/ no mostrarán ninguna referencia porque wrongPrefix//sadItem contiene dos / consecutivas.
  • Las que se realicen en lonelyItem/ no mostrarán ninguna referencia porque el objeto lonelyItem/ termina en /.

Muestra una lista de todos los archivos

Puedes usar listAll para obtener todos los resultados de un directorio. Se recomienda usarlo con directorios pequeños, ya que los resultados se almacenan en el búfer de la memoria. También es posible que la operación no muestre una instantánea coherente si se agregan o quitan objetos durante el proceso.

En el caso de una lista de gran tamaño, usa el método paginado list(), ya que listAll() almacena todos los resultados en el búfer de la memoria.

En el siguiente ejemplo, se muestra el funcionamiento de listAll.

Kotlin+KTX

val storage = Firebase.storage
val listRef = storage.reference.child("files/uid")

// You'll need to import com.google.firebase.storage.component1 and
// com.google.firebase.storage.component2
listRef.listAll()
    .addOnSuccessListener { (items, prefixes) ->
        for (prefix in prefixes) {
            // All the prefixes under listRef.
            // You may call listAll() recursively on them.
        }

        for (item in items) {
            // All the items under listRef.
        }
    }
    .addOnFailureListener {
        // Uh-oh, an error occurred!
    }

Java

StorageReference listRef = storage.getReference().child("files/uid");

listRef.listAll()
        .addOnSuccessListener(new OnSuccessListener<ListResult>() {
            @Override
            public void onSuccess(ListResult listResult) {
                for (StorageReference prefix : listResult.getPrefixes()) {
                    // All the prefixes under listRef.
                    // You may call listAll() recursively on them.
                }

                for (StorageReference item : listResult.getItems()) {
                    // All the items under listRef.
                }
            }
        })
        .addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                // Uh-oh, an error occurred!
            }
        });

Muestra una lista paginada de resultados

La API de list() impone un límite para la cantidad de resultados que se muestran. list() proporciona una vista de página coherente y expone un pageToken que permite controlar el momento en que se deben recuperar más resultados.

El pageToken codifica la ruta de acceso y la versión del último elemento que se mostró en el resultado anterior. Si se realiza una solicitud posterior con el pageToken, se mostrarán los elementos que vienen después de él.

El siguiente ejemplo muestra la paginación de un resultado:

Kotlin+KTX

fun listAllPaginated(pageToken: String?) {
    val storage = Firebase.storage
    val listRef = storage.reference.child("files/uid")

    // Fetch the next page of results, using the pageToken if we have one.
    val listPageTask = if (pageToken != null) {
        listRef.list(100, pageToken)
    } else {
        listRef.list(100)
    }

    // You'll need to import com.google.firebase.storage.component1 and
    // com.google.firebase.storage.component2
    listPageTask
        .addOnSuccessListener { (items, prefixes, pageToken) ->
            // Process page of results
            processResults(items, prefixes)

            // Recurse onto next page
            pageToken?.let {
                listAllPaginated(it)
            }
        }.addOnFailureListener {
            // Uh-oh, an error occurred.
        }
}

Java

public void listAllPaginated(@Nullable String pageToken) {
    FirebaseStorage storage = FirebaseStorage.getInstance();
    StorageReference listRef = storage.getReference().child("files/uid");

    // Fetch the next page of results, using the pageToken if we have one.
    Task<ListResult> listPageTask = pageToken != null
            ? listRef.list(100, pageToken)
            : listRef.list(100);

    listPageTask
            .addOnSuccessListener(new OnSuccessListener<ListResult>() {
                @Override
                public void onSuccess(ListResult listResult) {
                    List<StorageReference> prefixes = listResult.getPrefixes();
                    List<StorageReference> items = listResult.getItems();

                    // Process page of results
                    // ...

                    // Recurse onto next page
                    if (listResult.getPageToken() != null) {
                        listAllPaginated(listResult.getPageToken());
                    }
                }
            }).addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception e) {
                    // Uh-oh, an error occurred.
                }
            });
}

Soluciona errores

Si no actualizaste las reglas de seguridad a la versión 2, list() y listAll() fallarán. Actualízalas si ves el siguiente error:

Listing objects in a bucket is disallowed for rules_version = "1".
Please update storage security rules to rules_version = "2" to use list.

Otros errores posibles pueden indicar que el usuario no tiene el permiso adecuado. Para obtener más información sobre los errores, consulta Soluciona errores.