web-dev-qa-db-ja.com

FirebaseStorage:ディレクトリを削除する方法

FirebaseStorageは、ディレクトリを削除しようとすると常にエラー400を返します。つまり、次のようなものは常にエラー400を返します。

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

ただし、ファイルを削除しても問題ありません。のようなものはエラーを返しません:

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

ここで何が悪いのでしょうか?私はそれがFirebaseStorageでサポートされていないことはないと思います。ディレクトリからファイルを1つずつ削除するのはかなり不十分です(特に、上記のディレクトリに数百または数千ある場合)。

20
ishaq

googleグループから、ディレクトリを削除することはできません。 (Firebase Databaseの)どこかにファイルのリストを保持し、それらを1つずつ削除する必要があります。

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

機能のリクエストも提出しましたが、バグトラッカーは公開されていないため、共有できるリンクはありません。

15
ishaq

安全なgoogleクラウド機能のコンテキストから-次のように、Google Cloud Storage npmパッケージ(別名Google Cloud Storage API)を使用してディレクトリ全体を削除できます。

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

利用可能なその他のドキュメント GCS APIドキュメント

22
TheFastCat

2019年7月の時点で、フォルダーを一覧表示し、その内容を再帰的に削除できます。

      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

これを行う方法は次のようになります(最後のファイルを使用して、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

TheFastCatの回答とTeodor Ciurarのコメントに基づいて、ユーザーがFirebase Authenticationから削除されるとユーザーのフォルダーを削除する以下のFirebase Cloud Functionを作成しました。

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

2020年には、Firebase Storageフォルダを削除しても問題ないようです。以下のCloud Functions(Node.js Admin)で実行したところ、フォルダー、サブフォルダー、およびそれらのファイルが削除されました。 npmを使用してGoogle Cloud Storageをダウンロードしましたが、そのライブラリを物理的にインポートしなかったため、Firebase Storageが上記の機能とは異なり、この機能をサポートしているようです。多分彼らはそれを更新しました。動作していることをテストしました。

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

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

上記のように、ディレクトリの削除は無効です。 Firebase Database内のファイルのリストをクエリして、1つずつ削除する例を紹介します。これは私のクエリと呼び出しです。

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

これは、URLを取得してループし、そのストレージ参照にあるファイルを削除する私の関数です。

    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

ディレクトリを削除する唯一の方法は、すべてのファイルをループして1つずつ削除することです:

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

Firebase関数を使用してFirebase Storageのフォルダー内のファイルを削除する1つの解決策を次に示します。

Firebaseデータベースの/ MyStorageFilesInDatabaseTrackedHere/path1/path2にモデルが保存されていることを前提としています。

これらのモデルには、「filename」という名前のフィールドがあり、Firebase Storage内のファイルの名前が含まれます。

ワークフローは次のとおりです。

  1. モデルのリストを含むFirebaseデータベースのフォルダーを削除します
  2. Firebase関数を介してそのフォルダーの削除をリッスンします
  3. この関数は、フォルダーの子をループし、ファイル名を取得してストレージから削除します。

(免責事項:ストレージ内のフォルダーはこの関数の最後に残っているため、削除するには別の呼び出しを行う必要があります。)

// 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

26/5/2017ではディレクトリを削除する方法はありませんが、私のアルゴリズムを使用できます

このコードを使用します。

   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