3

I want to delete the folder "test" and everything that is in it.

I am sucessfuly able to delete the folder and all it's contents/subfolders in FirebaseStorage with the terminal using this code:

gsutil rm -r gs://bucketname.appspot.com/test/**

enter image description here

However when I tried to do it in java, it does not work.

    Storage storage = StorageOptions.getDefaultInstance().getService();
    String bucketName = "bucketname.appspot.com/test";
    Bucket bucket = storage.get(bucketName);
    bucket.delete(Bucket.BucketSourceOption.metagenerationMatch());

It throws this exception:

Exception in thread "FirebaseDatabaseEventTarget" com.google.cloud.storage.StorageException: Invalid bucket name: 'bucketname.appspot.com/test'
    at com.google.cloud.storage.spi.DefaultStorageRpc.translate(DefaultStorageRpc.java:202)
    at com.google.cloud.storage.spi.DefaultStorageRpc.get(DefaultStorageRpc.java:322)
    at com.google.cloud.storage.StorageImpl$4.call(StorageImpl.java:164)
    at com.google.cloud.storage.StorageImpl$4.call(StorageImpl.java:161)
    at com.google.cloud.RetryHelper.doRetry(RetryHelper.java:179)
    at com.google.cloud.RetryHelper.runWithRetries(RetryHelper.java:244)
    at com.google.cloud.storage.StorageImpl.get(StorageImpl.java:160)
    at xxx.backend.server_request.GroupRequestManager.deleteGroupStorage(GroupRequestManager.java:119)
    at xxx.backend.server_request.GroupRequestManager.deleteGroup(GroupRequestManager.java:26)
    at xxx.backend.server_request.ServerRequestListener.onChildAdded(ServerRequestListener.java:27)
    at com.google.firebase.database.core.ChildEventRegistration.fireEvent(ChildEventRegistration.java:65)
    at com.google.firebase.database.core.view.DataEvent.fire(DataEvent.java:49)
    at com.google.firebase.database.core.view.EventRaiser$1.run(EventRaiser.java:41)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Caused by: com.google.api.client.googleapis.json.GoogleJsonResponseException: 400 Bad Request
{
  "code" : 400,
  "errors" : [ {
    "domain" : "global",
    "message" : "Invalid bucket name: 'bucketname.appspot.com/test'",
    "reason" : "invalid"
  } ],
  "message" : "Invalid bucket name: 'bucketname.appspot.com/test'"
}

So then it does not exist? because when I run this code without /test:

    Storage storage = StorageOptions.getDefaultInstance().getService();
    String bucketName = "bucketname.appspot.com";
    Bucket bucket = storage.get(bucketName);
    bucket.exists(Bucket.BucketSourceOption.metagenerationMatch());

then exists returns true, no exception and I am able to list all the blobs.. But I want to delete all that is inside "/test".

Edit: Okay, I did get it to work like this, but I need to use a iterator. Is there a better solution? A wildcard or something?

    Storage storage = StorageOptions.getDefaultInstance().getService();
    String bucketName = "bucketname.appspot.com";
    Page<Blob> blobPage = storage.list(bucketName, Storage.BlobListOption.prefix("test/"));
    List<BlobId> blobIdList = new LinkedList<>();
    for (Blob blob : blobPage.iterateAll()) {
        blobIdList.add(blob.getBlobId());
    }
    storage.delete(blobIdList);
Linxy
  • 2,525
  • 3
  • 22
  • 37

2 Answers2

2

Buckets are the basic containers that hold your data. You have a bucket with name "bucketname.appspot.com". "bucketname.appspot.com/test" is your bucket name plus a folder, so its not a valid name of your bucket. By calling bucket.delete(...) you can delete only the whole bucket, but you cannot delete a folder in a bucket. Use GcsService to delete files or folders.

String bucketName = "bucketname.appspot.com";
GcsService gcsService = GcsServiceFactory.createGcsService(RetryParams.getDefaultInstance());
gcsService.delete(new GcsFilename(bucketName, "test"));
Yevgen
  • 4,519
  • 3
  • 24
  • 34
  • is the GcsService apart of the com.google.cloud:google-cloud-storage sdk? I don't seem to have it. (flexible env) – Linxy Apr 28 '17 at 19:39
  • It is a client library. Check here: https://cloud.google.com/storage/docs/reference/libraries – Yevgen Apr 28 '17 at 19:43
  • I already have that client library installed you linked, and GcsService doesn't seem to be included. But I did find it here: https://cloud.google.com/appengine/docs/standard/java/googlecloudstorageclient/javadoc/com/google/appengine/tools/cloudstorage/package-summary, apart of the AppEngine SDK, but that is under Standard Environment, and im using Flexible environment. – Linxy Apr 28 '17 at 19:51
  • `BlobId blobId = BlobId.of(bucketName, blobName); storage.delete(blobId);` Blob should be avaliable on both environments – Yevgen Apr 28 '17 at 19:54
1

I posted a possible solution over at https://stackoverflow.com/a/52580756/4752490 and will post it here too.

Here is one solution to delete files in a folder in Firebase Storage using Firebase Functions.

It assumes you have models stored under /MyStorageFilesInDatabaseTrackedHere/path1/path2 in your Firebase Database.

Those models will have a field named "filename" which will have the name of the file in Firebase Storage.

The workflow is:

  1. Delete the folder in Firebase Database that contains the list of models
  2. Listen for the deletion of that folder via Firebase Functions
  3. This function will loop over the children of the folder, obtain the filename and delete it in Storage.

(Disclaimer: the folder in Storage is still leftover at the end of this function so another call needs to be made to remove it.)

// 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);
});
Lucy
  • 436
  • 5
  • 8
  • When the OP tagged his question as java, please do respect that tag and provide a java solution, not some random code –  Jan 23 '20 at 18:29