FirebaseStorage:如何删除目录

时间:2016-06-10 13:33:57

标签: ios swift firebase firebase-storage

当我尝试删除目录时,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不支持它,因为逐个删除目录中的文件会非常蹩脚(特别是如果所述目录有100或1000个这样的话)。

13 个答案:

答案 0 :(得分:12)

从谷歌群组

,无法删除目录。您必须在某处(在Firebase数据库中)维护文件列表并逐个删除它们。

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

我还提交了功能请求,但由于他们的错误跟踪器不公开,因此没有可以分享的链接。

答案 1 :(得分:10)

在安全的Google云端功能环境中,您可以使用Google Cloud Storage npm软件包(也称为Google云端存储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`);
    }
  });

更多可用文档on GCS API docs

答案 2 :(得分:8)

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

答案 3 :(得分:5)

执行此操作的方法如下(使用最后一个文件,删除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);
});

答案 4 :(得分:4)

现在您知道我们无法删除Firebase存储中的文件夹。但是您可以在该文件夹中列出文件,然后删除每个文件。

这里有一个样品。

        // 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存储listAll()方法目前在软件包的开发版本5.0.0-dev.1中可用,您可以如上所示使用它。

答案 5 :(得分:2)

基于 TheFastCat 的回答和 Teodor Ciuraru 的评论,我创建了以下Firebase Cloud Function,当从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}/`
    })
})

答案 6 :(得分:1)

从2019年7月开始,您可以列出一个文件夹并递归删除其内容:

gl.copyTexSubImage2D

答案 7 :(得分:0)

  

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

    });


  }

答案 8 :(得分:0)

如上所述,删除目录无效。我分享了一个查询Firebase数据库中的文件列表并逐个删除它们的示例。这是我的查询和电话。

Get-AzureVM

这是我的函数循环,通过获取URL,然后删除该存储引用的文件。

$serviceName = "xxxx"
$vmName ="xxxx"
$vm= Get-AzureVM -ServiceName $serviceName -Name $vmName 
$disk =  Get-AzureDisk -DiskName  $vm.VM.OSVirtualHardDisk.DiskName
$location = $disk.Location

答案 9 :(得分:0)

这是使用Firebase功能删除Firebase存储中文件夹中文件的一种解决方案。

假定您具有存储在Firebase数据库中/ MyStorageFilesInDatabaseTrackedHere / path1 / path2下的模型。

这些模型将具有一个名为“ filename”的字段,该字段将具有Firebase Storage中文件的名称。

工作流程为:

  1. 在Firebase数据库中删除包含模型列表的文件夹
  2. 收听通过Firebase函数删除该文件夹的信息
  3. 此功能将遍历文件夹的子级,获取文件名并将其在存储中删除。

(免责声明:在此功能结束时,Storage中的文件夹仍然剩余,因此需要再次调用以将其删除。)

export class MyWidgetComponent implements OnChanges { 
  cssExternal$: Observable<any>; 
  ngOnChanges(changes: SimpleChanges) {
    const contentChanges = changes.content;
    if (contentChanges) {
      // ...some code
      this.url$ = new Subject();
      this.cssInternal$ = new Subject();

      this.cssExternal$ = this.url$.pipe(
        map((url: string) => {
          console.log('url in map', url);
          if (url.includes(window.location.origin)) {
            return url.replace(window.location.origin, this.url);
          }
          return url;
        }),
        mergeMap((url: string) => {
          return this._ApiService.makeRequest(url, ActionType.content).pipe(
            map(({ content }: any) => content)
          );
        })
      );

      this.css$ = merge(
        this.cssInternal$,
        this.cssExternal$
      );

      this.parseStyles(styleSheets);
    }       

  parseStyles(styleSheets: Element[]) {
    return styleSheets.forEach((element: HTMLElement) => {
      switch (element.localName) {
        // ...some code
        case 'link':
          const url = (element as HTMLLinkElement).href;
          console.log('url before next', url);
          this.url$.next(url);
          break;
        // ...some code
      }
    });
  }
}

答案 10 :(得分:0)

似乎删除目录的唯一方法是循环浏览所有文件并逐个删除它们:

const mapStateToProps = (state, props) => ({
  note: state.notes.find((note) => note.id === props.match.params.id
});

答案 11 :(得分:0)

我注意到,在删除 firebase 存储文件夹中的所有文件时,一段时间后,该文件夹也被删除。无需任何操作。

答案 12 :(得分:-1)

现代版本的“ Miki”答案,使用带有for await... of..的ES2018 Async/Await已删除文件计数器

const storage = firebase.storage();

const deleteFile = async (filePath) => {
    const ref = storage.ref(filePath);
    return await ref.delete();
};
const deleteFolderRecursive = async (folderPath) => {
    const ref = storage.ref(folderPath);
    const list = await ref.listAll();
    let filesDeleted = 0;

    for await (const fileRef of list.items) {
        await deleteFile(fileRef.fullPath);
        filesDeleted++;
    }
    for await (const folderRef of list.prefixes) {
        filesDeleted += await deleteFolderRecursive(folderRef.fullPath);
    }
    return filesDeleted;
};

// Usage
async deleteFolder(x) {
    try {
         const filesDeleted = deleteFolderRecursive('path/to/storage/folder');
         console.log(`${filesDeleted} files has been deleted`);
         // you can now, for instance, unblock the UI at this point
    } catch(err){
       // probably denied permissions or 'path/to/storage/folder' is not a folder
       console.error(err)
    }

}

如前所述,文件夹引用不会被删除,但至少它们不会像无法访问的文件那样从您的存储配额中拖出。