web-dev-qa-db-fra.com

FirebaseStorage: Comment supprimer un répertoire

FirebaseStorage renvoie toujours une erreur 400 lorsque j'essaie de supprimer un répertoire, c'est-à-dire que quelque chose comme le suivant renvoie toujours une erreur 400.

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

Cependant, la suppression d'un fichier fonctionne correctement, par exemple quelque chose comme ne renvoie pas d'erreur:

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

Que pourrais-je faire de mal ici? Je ne pense pas qu'il n'est pas pris en charge par FirebaseStorage car la suppression de fichiers d'un répertoire un par un serait assez boiteuse (surtout si ledit répertoire en contient 100s ou 1000s).

20
ishaq

du groupe Google, la suppression d'un répertoire n'est pas possible. Vous devez maintenir une liste de fichiers quelque part (dans la base de données Firebase) et les supprimer un par un.

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

J'ai également soumis la demande de fonctionnalité mais comme leur traqueur de bogues n'est pas public, il n'y a pas de lien que je puisse partager.

15
ishaq

Dans le contexte d'une fonction sécurisée de Google Cloud - vous pouvez supprimer un répertoire entier en utilisant le package npm de Google Cloud Storage (aka Google Cloud Storage API) comme ceci:

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

plus de documentation disponible sur les documents de l'API GCS

22
TheFastCat

Depuis juillet 2019, vous pouvez répertorier un dossier et supprimer son contenu de manière récursive:

      deleteFolderContents(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.deleteFolderContents(folderRef.fullPath);
            })
          })
          .catch(error => {
            console.log(error);
          });
      }

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

Un moyen de le faire pourrait être le suivant (avec le dernier fichier, se débarrasse de dir):

let ref = firebase.storage().ref(path);
ref.listAll().then(dir => {
  dir.items.forEach(fileRef => {
    var dirRef = firebase.storage().ref(fileRef.fullPath);
    dirRef.getDownloadURL().then(function(url) {
      var imgRef = firebase.storage().refFromURL(url);
      imgRef.delete().then(function() {
        // File deleted successfully 
      }).catch(function(error) {
        // There has been an error      
      });
    });
  });
}).catch(error => {
  console.log(error);
});
2
Marcos

Sur la base de la réponse de TheFastCat et du commentaire de Teodor Ciurar, j'ai créé la fonction Cloud Firebase ci-dessous, qui supprime le dossier d'un utilisateur lorsque l'utilisateur est supprimé de l'authentification Firebase.

const admin = require('firebase-admin')
const functions = require('firebase-functions')

const bucket = admin.storage().bucket()

exports.deleteUser = functions.auth.user().onDelete(async (user) => {
    const { uid } = user
    await bucket.deleteFiles({
        prefix: `${uid}/`
    })
})
0
Henrik Wassdahl

En 2020, la suppression du dossier Firebase Storage semble fonctionner. Je viens de le faire, dans mes fonctions cloud (Node.js Admin), ci-dessous et il supprime le dossier, les sous-dossiers et les fichiers qu'ils contiennent. J'ai téléchargé Google Cloud Storage à l'aide de npm, mais je n'ai de toute façon pas importé cette bibliothèque physiquement, et il semble que Firebase Storage supporte désormais cette fonctionnalité contrairement à ce que tout le monde a dit ci-dessus. Ils l'ont peut-être mis à jour. Je l'ai testé qu'il fonctionne.

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

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

Comme indiqué ci-dessus, la suppression d'un répertoire n'est pas valide. Je partage un exemple d'interrogation d'une liste de fichiers dans la base de données Firebase et de les supprimer un par un. Ceci est ma requête et mon appel.

    let messagePhotoQuery = messagesRef.child(group.key).child("messages").queryOrdered(byChild: "photoURL")
    deleteMessagePhotos(from: messagePhotoQuery)

Ceci est ma fonction en boucle pour obtenir l'URL, puis supprimer le fichier à cette référence de stockage.

    func deleteMessagePhotos(from photoQuery: FIRDatabaseQuery) {
    photoQuery.observeSingleEvent(of: .value, with: { (messagesSnapshot) in
        guard messagesSnapshot.exists() else { return }
        print(messagesSnapshot)
        for message in messagesSnapshot.children {
            let messageSnapshot = message as! FIRDataSnapshot
            let messageData = messageSnapshot.value as! [String: AnyObject]
            if let photoURL = messageData["photoURL"] as? String {
                let photoStorageRef = FIRStorage.storage().reference(forURL: photoURL)
                photoStorageRef.delete(completion: { (error) in
                    if let error = error {
                        print(error)
                    } else {
                        // success
                        print("deleted \(photoURL)")
                    }
                })
            }
        }
    })
}
0
trishcode

Il semble que la seule façon de supprimer un répertoire est de parcourir tous les fichiers et de les supprimer un par un:

async function DeleteFirebaseStorageFolder(directoryName: string) {
    const serviceAccount = require('../secret/adminSdkPrivateKey.json');

    admin.initializeApp({
        credential: admin.credential.cert(serviceAccount),
        storageBucket: 'gs://yourprojectname.appspot.com'
    });

    const bucket = admin.storage().bucket();
    const files = (await bucket.getFiles({ directory: folderName }))[0];

    const Deletions = [];

    files.forEach(file => {
        Deletions.Push(bucket.file(file.name).delete());
    })

    await Promise.all(Deletions);

    bucket.getFiles({ directory: folderName }).then((files) => {
        console.log('Remaining number of files: ' + (files[0].length).toString());
    })
}
DeleteFirebaseStorageFolder('myDirectoryName');
0
python481516

Voici une solution pour supprimer des fichiers dans un dossier du stockage Firebase à l'aide des fonctions Firebase.

Il suppose que vous avez des modèles stockés sous/MyStorageFilesInDatabaseTrackedHere/path1/path2 dans votre base de données Firebase.

Ces modèles auront un champ nommé "nom de fichier" qui aura le nom du fichier dans Firebase Storage.

Le workflow est:

  1. Supprimez le dossier de la base de données Firebase qui contient la liste des modèles
  2. Écoutez la suppression de ce dossier via les fonctions Firebase
  3. Cette fonction bouclera sur les enfants du dossier, obtiendra le nom du fichier et le supprimera dans le stockage.

(Avis de non-responsabilité: le dossier dans Storage est toujours disponible à la fin de cette fonction, il faut donc effectuer un autre appel pour le supprimer.)

// 1. Define your Firebase Function to listen for deletions on your path
exports.myFilesDeleted = functions.database
    .ref('/MyStorageFilesInDatabaseTrackedHere/{dbpath1}/{dbpath2}')
    .onDelete((change, context) => {

// 2. Create an empty array that you will populate with promises later
var allPromises = [];

// 3. Define the root path to the folder containing files
// You will append the file name later
var photoPathInStorageRoot = '/MyStorageTopLevelFolder/' + context.params.dbpath1 + "/" + context.params.dbpath2;

// 4. Get a reference to your Firebase Storage bucket
var fbBucket = admin.storage().bucket();

// 5. "change" is the snapshot containing all the changed data from your
// Firebase Database folder containing your models. Each child has a model
// containing your file filename
if (change.hasChildren()) {
    change.forEach(snapshot => {

        // 6. Get the filename from the model and
        // form the fully qualified path to your file in Storage
        var filenameInStorage = photoPathInStorageRoot + "/" + snapshot.val().filename;

        // 7. Create reference to that file in the bucket
        var fbBucketPath = fbBucket.file(filenameInStorage);

        // 8. Create a promise to delete the file and add it to the array
        allPromises.Push(fbBucketPath.delete());
    });
}

// 9. Resolve all the promises (i.e. delete all the files in Storage)
return Promise.all(allPromises);
});
0
Lucy

Au 26/5/2017 il n'y a aucun moyen de supprimer le répertoire Mais vous pouvez utiliser mon algorithme

Utilisez ce code.

   this.sliders = this.db.list(`users/${this.USER_UID}/website/sliders`) as FirebaseListObservable<Slider[]>



  /**
   * Delete image from firebase storage is take a string path of the image
   * @param _image_path
   */
  deleteImage(_image_path: string) {

    // first delete the image
    const storageRef = firebase.storage().ref();
    const imageRef = storageRef.child(_image_path);
    imageRef.delete().then(function() {
      console.log('file deleted');
      // File deleted successfully
    }).catch(function(error) {
      // Uh-oh, an error occurred!
      console.log(error);
    });

  }



  /**
   * Deletes multiple Sliders, it takes an array of ids
   * @param ids
   */
  deleteMutipleSliders(ids: any) {

    ids.forEach(id => {

      this.getSliderDetails(id).subscribe(slider => {

        let id = slider.$key; // i think this is not nesesery
        const imgPath = slider.path;

        this.deleteImage(imgPath);
      });

      return this.sliders.remove(id);

    });


  }
0
user7956520