Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get a list of all files in Cloud Storage in a Firebase app?

People also ask

How do I download multiple files from Firebase Storage?

There is no specific API to download multiple files. You'll just have to download them by calling the same API for each file. This user is first on the weekly Google Cloud leaderboard.


Since Firebase SDKs for JavaScript release 6.1, iOS release 6.4, and Android release version 18.1 all have a method to list files.

The documentation is a bit sparse so far, so I recommend checking out Rosário's answer for details.


Previous answer, since this approach can still be useful at times:

There currently is no API call in the Firebase SDK to list all files in a Cloud Storage folder from within an app. If you need such functionality, you should store the metadata of the files (such as the download URLs) in a place where you can list them. The Firebase Realtime Database and Cloud Firestore are perfect for this and allows you to also easily share the URLs with others.

You can find a good (but somewhat involved) sample of this in our FriendlyPix sample app. The relevant code for the web version is here, but there are also versions for iOS and Android.


As of May 2019, version 6.1.0 of the Firebase SDK for Cloud Storage now supports listing all objects from a bucket. You simply need to call listAll() in a Reference:

    // Since you mentioned your images are in a folder,
    // we'll create a Reference to that folder:
    var storageRef = firebase.storage().ref("your_folder");


    // Now we get the references of these images
    storageRef.listAll().then(function(result) {
      result.items.forEach(function(imageRef) {
        // And finally display them
        displayImage(imageRef);
      });
    }).catch(function(error) {
      // Handle any errors
    });

    function displayImage(imageRef) {
      imageRef.getDownloadURL().then(function(url) {
        // TODO: Display the image on the UI
      }).catch(function(error) {
        // Handle any errors
      });
    }

Please note that in order to use this function, you must opt-in to version 2 of Security Rules, which can be done by making rules_version = '2'; the first line of your security rules:

    rules_version = '2';
    service firebase.storage {
      match /b/{bucket}/o {
        match /{allPaths=**} {

I'd recommend checking the docs for further reference.

Also, according to setup, on Step 5, this script is not allowed for Node.js since require("firebase/app"); won't return firebase.storage() as a function. This is only achieved using import * as firebase from 'firebase/app';.


Since Mar 2017: With the addition of Firebase Cloud Functions, and Firebase's deeper integration with Google Cloud, this is now possible.

With Cloud Functions you can use the Google Cloud Node package to do epic operations on Cloud Storage. Below is an example that gets all the file URLs into an array from Cloud Storage. This function will be triggered every time something's saved to google cloud storage.

Note 1: This is a rather computationally expensive operation, as it has to cycle through all files in a bucket / folder.

Note 2: I wrote this just as an example, without paying much detail into promises etc. Just to give an idea.

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

  });

});

I hope this will give you the general idea. For better cloud functions examples, check out Google's Github repo full of Cloud Functions samples for Firebase. Also check out their Google Cloud Node API Documentation


Since there's no language listed, I'll answer this in Swift. We highly recommend using Firebase Storage and the Firebase Realtime Database together to accomplish lists of downloads:

Shared:

// 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]()

Upload:

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

Download:

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

For more information, see Zero to App: Develop with Firebase, and it's associated source code, for a practical example of how to do this.


I also encountered this problem when I was working on my project. I really wish they provide an end api method. Anyway, This is how I did it: When you are uploading an image to Firebase storage, create an Object and pass this object to Firebase database at the same time. This object contains the download URI of the 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);
        }
    });

Later when you want to download images from a folder, you simply iterate through files under that folder. This folder has the same name as the "folder" in Firebase storage, but you can name them however you want to. I put them in separate thread.

 @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) {

        }
    });

Now I have a list of objects containing the URIs to each image, I can do whatever I want to do with them. To load them into imageView, I created another 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;
}

This returns a list of Bitmap, when it finishes I simply attach them to ImageView in the main activity. Below methods are @Override because I have interfaces created and listen for completion in other 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);
    }
}

Note that I have to wait for List Image to be returned first and then call thread to work on List Bitmap. In this case, Image contains the 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);
}

Hopefully someone finds it helpful. It will also serve as a guild line for myself in the future too.


You can list files in a directory of firebase storage by listAll() method. To use this method, have to implement this version of firebase storage. 'com.google.firebase:firebase-storage:18.1.1'

https://firebase.google.com/docs/storage/android/list-files

Keep in mind that upgrade the Security Rules to version 2.


Combining some answers from this post and also from here, and after some personal research, for NodeJS with typescript I managed to accomplish this by using firebase-admin:

import * as admin from 'firebase-admin';
const getFileNames = () => {
  admin.storage().bucket().getFiles(autoPaginate: false).then(([files]: any) => {
    const fileNames = files.map((file: any) => file.name);
    return fileNames;
  })
 }

In my case I also needed to get all the files from a specific folder from firebase storage. According to google storage the folders don't exists but are rather a naming conventions. Anyway I managed to to this by adding { prefix: ${folderName}, autoPaginate: false } inside the getFiles function call so:

...
const getFileNames = (folderName: string) => {
  admin.storage().bucket().getFiles({ prefix: `${folderName}`, autoPaginate: false })
    .then(([files]: any) => {
    ...