user3116871
user3116871

Reputation: 333

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

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?

Upvotes: 9

Views: 14207

Answers (7)

Steve Nginyo
Steve Nginyo

Reputation: 301

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

Upvotes: 0

Meet
Meet

Reputation: 915

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

Upvotes: 1

Justice Addico
Justice Addico

Reputation: 94

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

Upvotes: 1

sun sreng
sun sreng

Reputation: 715

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

Upvotes: 9

Mahmoud Abu Alheja
Mahmoud Abu Alheja

Reputation: 3658

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.

Upvotes: 10

Peza
Peza

Reputation: 1437

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.

Upvotes: 15

Doug Stevenson
Doug Stevenson

Reputation: 317467

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.

Upvotes: 10

Related Questions