FirebaseStorage: How to Delete Directory

26,463

Solution 1

from google group, deleting a directory is not possible. You have to maintain a list of files somewhere (in Firebase Database) and delete them one by one.

https://groups.google.com/forum/#!topic/firebase-talk/aG7GSR7kVtw

I have also submitted the feature request but since their bug tracker isn't public, there's no link that I could share.

Solution 2

From the context of a secure google cloud function - you can delete an entire directory using the Google Cloud Storage npm package (aka Google Cloud Storage API) like so:

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

  return bucket.deleteFiles({
    prefix: `users/${userId}/`
  }, function(err) {
    if (err) {
      console.log(err);
    } else {
      console.log(`All the Firebase Storage files in users/${userId}/ have been deleted`);
    }
  });

more documentation available on GCS API docs

Solution 3

In 2020, deleting Firebase Storage folder seems to just work. I just did, in my Cloud Functions (Node.js Admin), below and it deletes folder, sub-folders, and files in them. I did download Google Cloud Storage using npm, but I didn't import that library in anyway physically, and it seems Firebase Storage is now supporting this feature unlike what everyone said above. Maybe they have updated it. I tested it that it is working.

admin.initializeApp({
    storageBucket: "bucket_name.appspot.com",
})

const bucket = admin.storage().bucket();
await bucket.deleteFiles({
   prefix: `${folderName}/`
});

Solution 4

You can list a folder and delete its contents recursively:

deleteFolder(path) {
  const ref = firebase.storage().ref(path);
  ref.listAll()
    .then(dir => {
      dir.items.forEach(fileRef => this.deleteFile(ref.fullPath, fileRef.name));
      dir.prefixes.forEach(folderRef => this.deleteFolder(folderRef.fullPath))
    })
    .catch(error => console.log(error));
}

deleteFile(pathToFile, fileName) {
  const ref = firebase.storage().ref(pathToFile);
  const childRef = ref.child(fileName);
  childRef.delete()
}

Solution 5

Now you know we cant delete folder in firebase storage. But you can list file inside that folder and remove each file.

Here a sample..

        // Create a root reference
        var storageRef = firebase.storage().ref();
        // Create a reference 
        var mountainsRef = storageRef.child("your root path");

        // Now we get the references of these files
        mountainsRef.listAll().then(function (result) {
            result.items.forEach(function (file) {
               file.delete();
            });
        }).catch(function (error) {
            // Handle any errors
        });

Flutter firebase storage listAll() method is currently available in the dev version of the package, in version 5.0.0-dev.1, which you can use as shown above.

Share:
26,463
ishaq
Author by

ishaq

Programmer, iOS

Updated on February 04, 2022

Comments

  • ishaq
    ishaq over 2 years

    FirebaseStorage always returns error 400 when I try to delete a directory i.e. something like the following always returns error 400.

    let storageRef = FIRStorage.storage().reference().child("path/to/directory")
    storageRef.deleteWithCompletion { (error) in
        print("error: \(error)") // always prints error code 400
    }
    

    However, deleting a file works fine e.g. something like doesn't return an error:

    let storageRef = FIRStorage.storage().reference().child("path/to/file.jpg")
    storageRef.deleteWithCompletion { (error) in
        print("error: \(error)") // works fine, error is nil
    }
    

    What could I be doing wrong here? I don't reckon it's not supported by FirebaseStorage because deleting files from a directory one by one would be pretty lame (specially if the said directory has 100s or 1000s of these).

  • Teodor Ciuraru
    Teodor Ciuraru almost 6 years
    Gave me an error. Try it with const bucket = admin.storage().bucket();, for me it works.
  • Julian Paolo Dayag
    Julian Paolo Dayag over 5 years
    This is working and is much more easier to implement. No complex codes or whatsoever.
  • Tom Walsh
    Tom Walsh over 4 years
    can you update this code to include deleteFile() and deleteFolderContents() functions
  • Miki
    Miki over 4 years
    @TomWalsh Done. deleteFolderContents is recursive thought.
  • Tom Walsh
    Tom Walsh over 4 years
    thanks, it was the deleteFolderContents I was particularly confused on though, what do you mean its recursive. And what does dir.prefixes return?
  • Miki
    Miki over 4 years
    @TomWalsh deleteFolderContents lists the directory contents, deletes all files in there and calls deleteFolderContents again for each folder it finds. That's what recursive means. Regarding prefixes, you can check firebase listAll documentation (firebase.google.com/docs/reference/js/…)
  • FangerZero
    FangerZero over 4 years
    @Miki Yeah it might delete the items inside the folders/directories, but it's not deleting the folders/Directories.
  • Miki
    Miki over 4 years
    @FangerZero Firebase Storage does not work with folders. Folders actually don't exists, only files. You can upload files to a specific location/path but their entire filesystem is closer to a flat hash table where you store path/file pairs, than to a file system with multiple folder levels.
  • Miki
    Miki over 4 years
    While correct you are processing all files in series. It would be nice to have all deletions executed in parallel. You can do that with async/await, but I would suggest to collect all promises returned by your async func in an array and process them all at once with Promise.all().
  • wal
    wal over 4 years
    if you are using firebase storage you may need to add rules_version = '2'; to your firebase rules otherwise ref.listAll() fails
  • coolcool1994
    coolcool1994 over 4 years
    Error in Typescript Node.js require('@google-cloud/storage')() can't be a function.
  • zeiteisen
    zeiteisen about 4 years
    This is really nice. But super slow. The log after deleting one folder said Function execution took 236960 ms, finished with status: 'ok'. It also needs a lot of RAM. I've set the function to use the max runtime ops const runtimeOpts = { timeoutSeconds: 540, memory: '2GB' }
  • Subhash Kumar
    Subhash Kumar almost 4 years
    @Miki: Can you please share the version of @google-cloud/storage npm as I'm not getting any storage.ref(path) function? Is there any option to pass the limit of files to deletion and recursion of the same as for all too much memory required?
  • Miki
    Miki almost 4 years
    @SubhashKumar, It is not storage.ref(path), it is storage().ref(path).
  • matth
    matth almost 4 years
    This shows getting a bucket reference through the admin API, and using the GCS API to delete the folder. The question was about deleting files from the firebase storage client API. So while it may be useful to people it's not an answer to the question that was asked.
  • sudo
    sudo over 3 years
    ^ Yeah, Promise.all is your friend here.
  • sudo
    sudo over 3 years
    Thanks! One thing, childRef.delete() returns a promise that you need to wait on. I posted an ES6 version of this answer too that uses async/await and does things in parallel.
  • sambecker
    sambecker over 3 years
    As @TeodorCiuraru points out, you don't need @google-cloud/storage if you already have firebase-admin!
  • danday74
    danday74 over 2 years