Lister des fichiers avec Cloud Storage sur Android

Cloud Storage for Firebase vous permet de lister le contenu de votre Cloud Storage bucket. Les SDK renvoient à la fois les éléments et les préfixes des objets sous la référence Cloud Storage actuelle.

Les projets qui utilisent l'API List nécessitent Cloud Storage for Firebase Rules version 2. Si vous disposez d'un projet Firebase existant, suivez les étapes décrites dans le guide sur les règles de sécurité.

list() utilise l' Google Cloud Storage List API. Dans Cloud Storage for Firebase, nous utilisons / comme délimiteur, ce qui nous permet d'émuler la sémantique du système de fichiers. Pour permettre une traversée efficace des grands buckets hiérarchiques Cloud Storage, l'API List renvoie les préfixes et les éléments séparément. Par exemple, si vous importez un fichier /images/uid/file1,

  • root.child('images').listAll() renvoie /images/uid comme préfixe.
  • root.child('images/uid').listAll() renvoie le fichier en tant qu'élément.

Le Cloud Storage for Firebase SDK ne renvoie pas les chemins d'objet qui contiennent deux / consécutifs ou qui se terminent par un /. Prenons l'exemple d'un bucket contenant les objets suivants :

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

Les opérations de liste sur les éléments de ce bucket donnent les résultats suivants :

  • L'opération de liste à la racine renvoie les références à correctPrefix, wrongPrefix et lonelyItem en tant que prefixes.
  • L'opération de liste dans correctPrefix/ renvoie les références à correctPrefix/happyItem en tant que items.
  • L'opération de liste dans wrongPrefix/ ne renvoie aucune référence car wrongPrefix//sadItem contient deux / consécutifs.
  • L'opération de liste dans lonelyItem/ ne renvoie aucune référence car l'objet lonelyItem/ se termine par /.

Lister tous les fichiers

Vous pouvez utiliser listAll pour récupérer tous les résultats d'un répertoire. Il est préférable de l'utiliser pour les petits répertoires, car tous les résultats sont mis en mémoire tampon. L'opération peut également ne pas renvoyer d'instantané cohérent si des objets sont ajoutés ou supprimés pendant le processus.

Pour une liste volumineuse, utilisez la méthode list() paginée, car listAll() met en mémoire tampon tous les résultats.

L'exemple suivant illustre listAll.

Kotlin

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

Paginer les résultats d'une liste

L'API list() limite le nombre de résultats qu'elle renvoie. list() fournit une vue de page cohérente et expose un pageToken qui permet de contrôler le moment où des résultats supplémentaires doivent être récupérés.

Le pageToken encode le chemin d'accès et la version du dernier élément renvoyé dans le résultat précédent. Dans une requête ultérieure utilisant le pageToken, les éléments qui suivent le pageToken sont affichés.

L'exemple suivant montre comment paginer un résultat :

Kotlin

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

Gérer les erreurs

list() et listAll() échouent si vous n'avez pas mis à niveau les règles de sécurité vers la version 2. Mettez à niveau vos règles de sécurité si vous voyez cette erreur :

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

D'autres erreurs possibles peuvent indiquer que l'utilisateur ne dispose pas de l'autorisation appropriée. Pour en savoir plus sur les erreurs, consultez la section Gérer les erreurs.