121 votes

Comment obtenir une liste de tous les fichiers dans le stockage en nuage dans une application Firebase ?

Je travaille sur le téléchargement d'images, tout fonctionne bien, mais j'ai 100 photos et je voudrais toutes les afficher dans mon site Web. View J'obtiens la liste complète des images dans un dossier, mais je ne trouve pas d'API pour ce travail.

0 votes

Pouvez-vous afficher un code complet de la solution ?

97voto

Frank van Puffelen Points 16029

Depuis que les SDK Firebase pour JavaScript version 6.1 , Version 6.4 d'iOS et Version 18.1 de la version Android ont tous une méthode pour lister les fichiers.

Le site documentation est un peu clairsemée jusqu'à présent, donc je recommande de vérifier Réponse de Rosário pour les détails.


Réponse précédente, car cette approche peut encore être utile à certains moments :

Il n'existe actuellement aucun appel d'API dans le SDK de Firebase pour répertorier tous les fichiers d'un dossier de stockage en nuage à partir d'une application. Si vous avez besoin d'une telle fonctionnalité, vous devez stocker les métadonnées des fichiers (telles que les URL de téléchargement) à un endroit où vous pouvez les lister. Le site Base de données en temps réel Firebase et Cloud Firestore sont parfaits pour cela et vous permettent également de partager facilement les URL avec d'autres personnes.

Vous pouvez trouver un bon exemple (mais un peu compliqué) de ceci dans notre page FriendlyPix exemple d'application. Le code pertinent pour la version web est ici mais il existe également des versions pour iOS et Android.

0 votes

Si je garde l'URL de téléchargement, ne pas avoir des problèmes que firebase révoquer l'url pleine aspiration ?

1 votes

Firebase ne révoque pas automatiquement une URL de téléchargement et elle n'expire pas non plus. Vous pouvez les révoquer à partir de l'onglet Stockage de la page d'accueil. Console Firebase mais c'est le seul moyen que je connaisse pour les rendre invalides.

0 votes

Quel est le seau ? et qu'est-ce que c'est ?

36voto

cozbay Points 13

Depuis mars 2017 : Avec l'ajout de Fonctions Firebase Cloud et l'intégration plus poussée de Firebase dans Google Cloud, cela est désormais possible.

Avec Cloud Functions, vous pouvez utiliser le paquet Google Cloud Node pour effectuer les opérations suivantes épique opérations sur le stockage en nuage. Voici un exemple qui récupère toutes les URL de fichiers dans un tableau à partir de Cloud Storage. Cette fonction sera déclenchée à chaque fois que quelque chose est enregistré dans le stockage en nuage de Google.

Note 1 : Il s'agit d'une opération assez coûteuse en termes de calcul, car elle doit parcourir tous les fichiers d'un seau / dossier.

Note 2 : J'ai écrit ceci juste à titre d'exemple, sans accorder beaucoup de détails aux promesses, etc. Juste pour donner une idée.

const functions = require('firebase-functions');
const gcs = require('@google-cloud/storage')();

// let's trigger this function with a file upload to google cloud storage

exports.fileUploaded = functions.storage.object().onChange(event => {

  const object = event.data; // the object that was just uploaded
  const bucket = gcs.bucket(object.bucket);
  const signedUrlConfig = { action: 'read', expires: '03-17-2025' }; // this is a signed url configuration object

  var fileURLs = []; // array to hold all file urls 

  // this is just for the sake of this example. Ideally you should get the path from the object that is uploaded :)
  const folderPath = "a/path/you/want/its/folder/size/calculated";

  bucket.getFiles({ prefix: folderPath }, function(err, files) {
    // files = array of file objects
    // not the contents of these files, we're not downloading the files. 

    files.forEach(function(file) {
      file.getSignedUrl(signedUrlConfig, function(err, fileURL) {
        console.log(fileURL);
        fileURLs.push(fileURL);
      });
    });

  });

});

J'espère que cela vous donnera une idée générale. Pour de meilleurs exemples de fonctions en nuage, consultez Le dépôt Github de Google regorge d'échantillons de Cloud Functions pour Firebase. . Consultez également leur Documentation de l'API Google Cloud Node

38 votes

C'est trop stupide que firebase n'ajoute pas simplement cette api dans le sdk de firebase.

4 votes

@Thaina Je pense que cela a à voir avec l'échelle. Ils doivent penser non seulement aux petites applications mais aussi aux géants. Qu'en est-il si un chemin a des milliers de fichiers. Cette opération consommerait beaucoup de puissance de calcul et il faudrait se référer à une base de données pour chaque appel apparemment innocent et simple. Plus j'ai approfondi l'utilisation de Firebase à l'échelle, plus je comprends pourquoi certains compromis ont été faits.

1 votes

Il incombe donc au consommateur de l'API de connaître le risque et d'essayer de choisir une méthode qui puisse évoluer. Mais être surprotecteur et couper notre option n'est pas une bonne décision. Ils peuvent facturer la charge lourde si elle est vraiment coûteuse.

20voto

Mike McDonald Points 8728

Comme il n'y a pas de langue indiquée, je vais répondre en Swift. Nous recommandons vivement l'utilisation conjointe de Firebase Storage et de la base de données en temps réel de Firebase pour réaliser des listes de téléchargements :

Partagé :

// Firebase services
var database: FIRDatabase!
var storage: FIRStorage!
...
// Initialize Database, Auth, Storage
database = FIRDatabase.database()
storage = FIRStorage.storage()
...
// Initialize an array for your pictures
var picArray: [UIImage]()

Télécharger :

let fileData = NSData() // get data...
let storageRef = storage.reference().child("myFiles/myFile")
storageRef.putData(fileData).observeStatus(.Success) { (snapshot) in
  // When the image has successfully uploaded, we get it's download URL
  let downloadURL = snapshot.metadata?.downloadURL()?.absoluteString
  // Write the download URL to the Realtime Database
  let dbRef = database.reference().child("myFiles/myFile")
  dbRef.setValue(downloadURL)
}

Télécharger :

let dbRef = database.reference().child("myFiles")
dbRef.observeEventType(.ChildAdded, withBlock: { (snapshot) in
  // Get download URL from snapshot
  let downloadURL = snapshot.value() as! String
  // Create a storage reference from the URL
  let storageRef = storage.referenceFromURL(downloadURL)
  // Download the data, assuming a max size of 1MB (you can change this as necessary)
  storageRef.dataWithMaxSize(1 * 1024 * 1024) { (data, error) -> Void in
    // Create a UIImage, add it to the array
    let pic = UIImage(data: data)
    picArray.append(pic)
  })
})

Pour plus d'informations, voir De zéro à l'application : Développer avec Firebase et c'est le code source associé pour un exemple pratique de la manière de procéder.

3 votes

Mais comment obtenir le même résultat avec Cloud Firestore) ?

5voto

Andrea Points 41

Une solution de contournement peut être de créer un fichier (par exemple list.txt) sans rien à l'intérieur, dans ce fichier vous pouvez définir les métadonnées personnalisées (qui est une Map< String, String>) avec la liste de toutes les URL du fichier.
Ainsi, si vous avez besoin de télécharger tous les fichiers d'un fodler, vous téléchargez d'abord les métadonnées du fichier list.txt, puis vous itérez à travers les données personnalisées et téléchargez tous les fichiers avec les URL dans la carte.

4 votes

Oui, il s'agit d'une solution de contournement, mais elle ne peut pas gérer les écritures simultanées dans un seul list.txt.

5voto

Tao Points 85

J'ai également rencontré ce problème lorsque je travaillais sur mon projet. Je souhaite vraiment qu'ils fournissent une méthode d'api de fin. Quoi qu'il en soit, voici comment j'ai procédé : Lorsque vous téléchargez une image vers le stockage Firebase, créez un objet et passez cet objet à la base de données Firebase en même temps. Cet objet contient l'URI de téléchargement de l'image.

trailsRef.putFile(file).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
        @Override
        public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
            Uri downloadUri = taskSnapshot.getDownloadUrl();
            DatabaseReference myRef = database.getReference().child("trails").child(trail.getUnique_id()).push();
            Image img = new Image(trail.getUnique_id(), downloadUri.toString());
            myRef.setValue(img);
        }
    });

Plus tard, lorsque vous voudrez télécharger des images d'un dossier, il vous suffira d'itérer parmi les fichiers de ce dossier. Ce dossier a le même nom que le "dossier" dans le stockage Firebase, mais vous pouvez les nommer comme vous le souhaitez. Je les ai mis dans un fil séparé.

 @Override
protected List<Image> doInBackground(Trail... params) {

    String trialId = params[0].getUnique_id();
    mDatabase = FirebaseDatabase.getInstance().getReference();
    mDatabase.child("trails").child(trialId).addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            images = new ArrayList<>();
            Iterator<DataSnapshot> iter = dataSnapshot.getChildren().iterator();
            while (iter.hasNext()) {
                Image img = iter.next().getValue(Image.class);
                images.add(img);
            }
            isFinished = true;
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });

Maintenant que j'ai une liste d'objets contenant les URI de chaque image, je peux faire ce que je veux avec eux. Pour les charger dans imageView, j'ai créé un autre thread.

    @Override
protected List<Bitmap> doInBackground(List<Image>... params) {

    List<Bitmap> bitmaps = new ArrayList<>();

    for (int i = 0; i < params[0].size(); i++) {
        try {
            URL url = new URL(params[0].get(i).getImgUrl());
            Bitmap bmp = BitmapFactory.decodeStream(url.openConnection().getInputStream());
            bitmaps.add(bmp);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    return bitmaps;
}

Cela renvoie une liste de Bitmap, quand cela se termine, je les attache simplement à ImageView dans l'activité principale. Les méthodes ci-dessous sont @Override car j'ai créé des interfaces et j'écoute l'achèvement dans d'autres threads.

    @Override
public void processFinishForBitmap(List<Bitmap> bitmaps) {
    List<ImageView> imageViews = new ArrayList<>();
    View v;
    for (int i = 0; i < bitmaps.size(); i++) {
        v = mInflater.inflate(R.layout.gallery_item, mGallery, false);
        imageViews.add((ImageView) v.findViewById(R.id.id_index_gallery_item_image));
        imageViews.get(i).setImageBitmap(bitmaps.get(i));
        mGallery.addView(v);
    }
}

Notez que je dois d'abord attendre que List Image soit renvoyée, puis appeler le thread pour travailler sur List Bitmap. Dans ce cas, l'image contient l'URI.

    @Override
public void processFinish(List<Image> results) {
    Log.e(TAG, "get back " + results.size());

    LoadImageFromUrlTask loadImageFromUrlTask =  new LoadImageFromUrlTask();
    loadImageFromUrlTask.delegate = this;
    loadImageFromUrlTask.execute(results);
}

J'espère que quelqu'un le trouvera utile. Il servira également de ligne de guilde pour moi-même à l'avenir.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X