Delete a file from firebase storage using download url with Cloud Functions
Asked Answered
P

7

9

I have a collection of profiles in my Firestore db and a field named "profilePicture" with a downloadUrl as the value.

Im using cloud functions and been trying for a long time to figure out how to delete the profilePicture when the profile is deleted.

I know how to create a trigger when the profile is deleted and get the profile picture downloadUrl, but how do I delete the file from storage with only the downloadUrl?

Perla answered 20/4, 2018 at 15:41 Comment(3)
How did you generate the download URL?Trimetric
@DougStevenson I just retrieved it from the meta data when storing the picture on the device using swift.Perla
This is link answer the QuestionAinslee
T
10

My understanding is that the node SDK for Cloud Storage can't convert HTTP URLs into file paths within a storage bucket. Instead, you should be storing the file path along with the download URL in document. This will make it possible for to build a File object that can be used to delete the image when it's time to do so.

Trimetric answered 20/4, 2018 at 15:58 Comment(5)
That what I was thinking. I'm gonna go with your solution so I will mark your answer as correct.Perla
but you can extract path file from url ,see my answer belowGiraudoux
@MahmoudAbuElheja Firebase Storage does not guarantee the format of that URL. If you depend on its format, your code could break in the future. That's a risk you will have to take.Trimetric
@DougStevenson thanks for notice me , but are you sure from that because i tested this approach on multi file on storage and work fine ! , so what the case maybe not work with this ?Giraudoux
@MahmoudAbuElheja Just because something works today, that doesn't mean in will work in the future. There is no documentation explaining the format of the URL, which implies that the Firebase team might feel the need to change it some day.Trimetric
E
15

The firebase storage documentation provides a method refFromURL(url) that can be used on a Storage instance. It states the url argument can be:

A URL in the form:

1) a gs:// URL, for example gs://bucket/files/image.png

2) a download URL taken from object metadata.

Based (2) above, it seems like an HTTP URL should also work. However it probably is better practise to store a path string, as the tokens on the HTTP URLs can get rotated by Firebase.

Eyesore answered 25/5, 2018 at 8:4 Comment(0)
T
10

My understanding is that the node SDK for Cloud Storage can't convert HTTP URLs into file paths within a storage bucket. Instead, you should be storing the file path along with the download URL in document. This will make it possible for to build a File object that can be used to delete the image when it's time to do so.

Trimetric answered 20/4, 2018 at 15:58 Comment(5)
That what I was thinking. I'm gonna go with your solution so I will mark your answer as correct.Perla
but you can extract path file from url ,see my answer belowGiraudoux
@MahmoudAbuElheja Firebase Storage does not guarantee the format of that URL. If you depend on its format, your code could break in the future. That's a risk you will have to take.Trimetric
@DougStevenson thanks for notice me , but are you sure from that because i tested this approach on multi file on storage and work fine ! , so what the case maybe not work with this ?Giraudoux
@MahmoudAbuElheja Just because something works today, that doesn't mean in will work in the future. There is no documentation explaining the format of the URL, which implies that the Firebase team might feel the need to change it some day.Trimetric
G
10

for admin.storage.Storage is no build in method for get reference from url for storage

but you can extract file path from URL ,by remove baseUrl and do some code replace on URL

im create method for this task to accept url from storage project and return path

function getPathStorageFromUrl(url:String){

    const baseUrl = "https://firebasestorage.googleapis.com/v0/b/project-80505.appspot.com/o/";

    let imagePath:string = url.replace(baseUrl,"");

    const indexOfEndPath = imagePath.indexOf("?");

    imagePath = imagePath.substring(0,indexOfEndPath);
    
     imagePath = imagePath.replace("%2F","/");
    
 
    return imagePath;
}

NOTE : You must replace baseUrl for every project, you can find it by open any image in you storage , and copy it from URL in browser from start to end of last slash '/'

Ex :

Some image link on my storage : 
https://firebasestorage.googleapis.com/v0/b/project-80505.appspot.com/o/RequestsScreenshot%2F-M6CA-2bG2aP_WwOF-dR__1i5056O335?alt=media&token=d000fab7

the base URL will be 
https://firebasestorage.googleapis.com/v0/b/project-80505.appspot.com/o/ 

now after get path call file to delete it from storage

const storage = admin.storage();

const imagePath:string = getPathStorageFromUrl(obj.imageUrl);

storage.bucket().file(imagePath).delete().catch((err) => console.error(err));

NOTE : There is no documentation explaining the format of the URL, which implies that the Firebase team might feel the need to change it some day , mean maybe will not work in the future if format is change.

Giraudoux answered 11/6, 2020 at 14:16 Comment(0)
A
9

In Angular I use this to delete file from Cloud Firestore by downloadURL

constructor(private storage: AngularFireStorage) {}

onDeleteAttachment(downloadURL: string) {
  this.storage.storage.refFromURL(downloadURL).delete();
}
Acarid answered 21/10, 2020 at 2:42 Comment(1)
There's a similar method in Kotlin storageRef.getReferenceFromUrl(url) your answer helped me find it. Thanks.Cursor
H
1

Mahmoud's answer need a little edit .. it works tho .. He is doing the replacements wrongly and might not work if you have nested directories or spaced filenames in your storage

getPathStorageFromUrl(url:String){

        const baseUrl = "https://firebasestorage.googleapis.com/v0/b/project-80505.appspot.com/o/";
    
        let imagePath:string = url.replace(baseUrl,"");
    
        const indexOfEndPath = imagePath.indexOf("?");
    
        imagePath = imagePath.substring(0,indexOfEndPath);
        
        imagePath = imagePath.replace(/%2F/g,"/");
        
        imagePath = imagePath.replace(/%20/g," ");
     
        return imagePath;
    }
Hopi answered 16/3, 2021 at 11:43 Comment(0)
A
1

confing.js

import firebase from 'firebase/app'
import "firebase/firestore";
import "firebase/storage";

const firebaseConfig = {
            apiKey: "XXXX",
            authDomain: "XXXXX.firebaseapp.com",
            databaseURL: "https://XXXX-app-web.firebaseio.com",
            projectId: "XXXX",
            storageBucket: "XXXX-app-web.appspot.com",
            messagingSenderId: "XXXXXX",
            appId: "1:XXX:web:XXXX",
            measurementId: "G-XXXX"
};
firebase.initializeApp(firebaseConfig);
export const firestore = firebase.firestore();
export const storageRef = firebase.storage();

export default firebase;

Button.js

import React from 'react';
import {firestore,storageRef} from './Config';

function removeFile(id,downloadUrl) {
  const storageRefa = storageRef.refFromURL(downloadUrl);

  storageRefa.delete().then(() => {
    firestore.collection("All_Files").doc(id).delete().then((response) => {
      console.log('delete response', response)
    }).catch((error) => {
      console.log('delete error', error)
    })
  }).catch((error) => {
    console.log('delete error', error)
  });
}
export default function MediaCard(props) {
  return (
    <>
           <Button
              onClick={() =>{
                removeFile(props.ID,props.downloadUrl)
              }}
              variant="contained"
              color="secondary"
          >
            Delete
          </Button>
    </>
  );
}
Ainslee answered 19/3, 2021 at 8:19 Comment(1)
refFromURL exists on the Web SDK, not in the cloud functions SDKs, which the question asks.Bindman
H
0

I think the new js sdk can delete using the full url provided during saving

//url = "https://**url provided in downloadURL while saving**"
deleteimage(url: string){
    const storage = getStorage();
    var storageRef = ref(storage, url);
    // console.log(storageRef.fullPath)
    deleteObject(storageRef).then(() => {
      // File deleted successfully
    }).catch((error) => {
      // Uh-oh, an error occurred!
    });
  }
saveImage(){
 const storage = getStorage();
const storageRef = ref(storage, 'images/rivers.jpg');
const uploadTask = uploadBytesResumable(storageRef, file);
uploadTask.on('state_changed', 
  (snapshot) => {
    // Observe state change events such as progress, pause, and resume
    // Get task progress, including the number of bytes uploaded and the total number of bytes to be uploaded
    const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
    console.log('Upload is ' + progress + '% done');
    switch (snapshot.state) {
      case 'paused':
        console.log('Upload is paused');
        break;
      case 'running':
        console.log('Upload is running');
        break;
    }
  }, 
  (error) => {
    // Handle unsuccessful uploads
  }, 
  () => {
    // Handle successful uploads on complete
    getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => {
////use this download url to delete
      console.log('File available at', downloadURL);
    });
  }
);
}
Hillegass answered 3/6, 2024 at 9:53 Comment(2)
Dart also has a deletefromurl. But I wonder if it safe to leave it like that? Maybe the implementation of deletefromurl does find the path where the file is located.Jovanjove
Should just throw an errorHillegass

© 2022 - 2025 — McMap. All rights reserved.