Delete Firebase Storage image url with download url - firebase

I am using Firebase storage and Realtime Database for storing the image and its download url respectively.The filename is generated in a random manner with which download url is generated and saved to the realtime database.
Scenario:
If user uploads new Image(For e.g Profile Image) I want to delete the old image with the help of downloadImageurl(Download image url is generated when image is uploaded initially and same is saved in the realtime database).How the old image can be deleted?I have tried below code but for it to work I must get filename.
gcs
.bucket("e**********.appspot.com") // find it in Firebase>Storage>"gs://...." copy without gs
//or go to console.cloud.google.com/ buckets and copy name
.file("images/" +event.params.uid+"/"+filename) //file location in my storage
.delete()
.then(() => {
console.log(`gs://${bucketName}/${filename} deleted.`);
})
.catch(err => {
console.error('ERROR-DELETE:', err+ " filename: "+filename);
});

This may help you out.
This code will fetch the name of file from the URL and will delete that file. Currently this solution works for me!
Code
import * as firebase from 'firebase';
...
let name = imagePath.substr(imagePath.indexOf('%2F') + 3, (imagePath.indexOf('?')) - (imagePath.indexOf('%2F') + 3));
name = name.replace('%20',' ');
let storagePath = firebase.storage().ref();
storagePath.child(`images/${name}`).delete();

Depending on what you want:
Keep the original image and being able to delete it manually in the future.
Delete it immediately after the thumbnail is generated.
I suppose you are using this example
1- You have to store the filePath in your db. Then whenever you want to delete it from your front:
import * as firebase from 'firebase';
...
const store = firebase.storage().ref();
// Depending on which db you use and how you store, you get the filePath and delete it:
store.child(image.filePath).delete();
2- Continue the promise from the firebase function like this:
// ...LAST PART OF THE EXAMPLE...
.then(() => {
// Add the URLs to the Database
return admin.database().ref('images').push({path: fileUrl, thumbnail: thumbFileUrl});
}).then(() => {
// ...PART YOU CAN ADD TO DELETE THE IMAGE UPLOADED
const bucket = gcs.bucket(bucket);
bucket.file(filePath).delete();
})
"bucket" is the const previously created:
const bucket = gcs.bucket(event.data.bucket);
as well as "filePath":
const filePath = event.data.name;

To delete an image with the url, you can use refFromUrl() function to get the ref then delete it easily
const storage = firebase.storage();
storage.refFromURL(imageUrl).delete()

const downloadUrl = "https://firebasestorage.googleapis.com/v0/b/***.appspot.com/o/***?alt=media&token=***";
The first *** represents FIREBASE_STORAGE_BUCKET
The second *** represents location of file in bucket
The third *** represents token for public access image/file
As a web developer, you're aware that URI are encoded such as
"#" = "%40",
"$" = "%24",
" " = "%20", etc.
Since we are using JavaScript, what we can do is decode URI like so to get exact path
const path = decodeURIComponent(downloadUrl.split("o/")[1].split("?")[0]);
return await bucket
.file(path)
.delete()
.then(() => true)
.catch((error) => {
throw new TypeError(`deleteImages ${error}`);
});

Related

Flutter : How to upload image to firestore in form

Hay, I'm new in firestore and a little bit confused about uploading data to firestore. let's take an example, I have a form format like this :
so, there is a data (name, DoB) form and upload image form. as far I know is to store data collection (like name and Date of Brith section) is using the cloud_firestore plugin, otherwise to store the image file is using firebase_store plugin.
then, how do I use both plugins at the same time when uploading forms like this? or is there another method to upload image with a form?
Thanks.
You need to first upload the image to firebse_storage , get a link and create the firestore document.
example
// upload the file helper
Future<String?> uploadFile(FilePickerResult? fileName) async {
Uint8List? fileBytes = fileName!.files.first.bytes;
// Create a Reference to the file
var filename = DateTime.now().toLocal().toIso8601String();
if (kIsWeb) {
firebase_storage.Reference ref = firebase_storage.FirebaseStorage.instance
.refFromURL(storageRefFbS)
.child("files")
.child(filename + "." + fileName.files.first.extension!);
await ref.putData(fileName.files.first.bytes!);
var dwonloadurl = await ref.getDownloadURL();
log(dwonloadurl);
return dwonloadurl;
}
}
//upload a file/image
var downloadUrl =
await firebaseHelper.uploadFile(myPickedFile);
// save the data
FirebaseFirestore.instance
.collection("myData")
.set({
"sname": "name",
"url":downloadUrl,
});

How can I get my http URL from the PDF I've uploaded in Firebase?

Sample image
I'm creating a project that needs an http URL instead firebase gave me a gs URL, how can I get the HTTP URL for my uploaded PDF files?
In that image, you should see the Name of the file on the right-hand side as a hyperlink.
So long as a valid access token (bottom of that same side menu) exists, you can access it. Just make sure the URL link includes the access token on the end.
Example: ?alt=media&token=53063556-5482-4c09-bd6f-732533b3bfdb
If you wanna access the link manually, just click on the hyperlink of document name on right sidebar.(Ang-katipunan.pdf)
But, if you want to automatically pass that link into a a db doc for example,
You should try make use of getDownloadURL and pass that as a field in the firestore document(if using firestore).
Here's an example of passing a URL of a photo as a "imageURL" field.
const imageUpload = async () => {
const uri = img;
const childPath = `imgs/${Math.random().toString(36)}`; // This math random is not very imp, just to make sure its generating a random link
const resp = await fetch(uri);
const blob = await resp.blob();
const task = firebase
.storage()
.ref()
.child(childPath)
.put(blob);
const onTaskCompleted = () => {
task.snapshot.ref.getDownloadURL().then((snapshot) =>{ // this is imp
saveImage(snapshot);
})
};
const onTaskError = snapshot => {
console.log(snapshot);
};
task.on("state_changed", onTaskError, onTaskCompleted );
};
then
const saveImage = (downloadURL) => {
firebase.firestore()
.collection('allImages')
.add({
downloadURL, //this is the link
name,
})
}
Change according to your docs

how to create refFromURL with admin privilege on cloud functions?

I want to have a reference to an image using its http URL when firestore update cloud function triggered so that i can take the url from change provide by onUpdate() function and use it to get a reference to the image on firebase storage and delete it.
In order to delete a file stored in Cloud Storage for Firebase from a Cloud Function you will need to create a File object based on:
The Bucket instance this file is attached to;
The name of the file,
and then call the delete() method
as detailed in the Node.js library documentation https://cloud.google.com/nodejs/docs/reference/storage/2.0.x/File.
Here is an example of code from the documentation:
const storage = new Storage();
const bucketName = 'Name of a bucket, e.g. my-bucket';
const filename = 'File to delete, e.g. file.txt';
// Deletes the file from the bucket
storage
.bucket(bucketName)
.file(filename)
.delete()
.then(() => {
console.log(`gs://${bucketName}/${filename} deleted.`);
})
.catch(err => {
console.error('ERROR:', err);
});
From your question, I understand that your app clients don't have the bucket and file names as such and only have a download URL (probably generated through getDownloadURL if it is a web app, or the similar method for other SDKs).
So the challenge is to derive the bucket and file names from a download URL.
If you look at the format of a download URL you will find that it is composed as follows:
https://firebasestorage.googleapis.com/v0/b/<your-project-id>.appspot.com/o/<your-bucket-name>%2F<your-file-name>?alt=media&token=<a-token-string>
So you just need to use a set of Javascript methods like indexOf(), substring() and/or slice() to extract the bucket and file names from the download URL.
Based on the above, your Cloud Function code could then look like:
const storage = new Storage();
.....
exports.deleteStorageFile = functions.firestore
.document('deletionRequests/{requestId}')
.onUpdate((change, context) => {
const newValue = change.after.data();
const downloadUrl = newValue.downloadUrl;
// extract the bucket and file names, for example through two dedicated Javascript functions
const fileBucket = getFileBucket(downloadUrl);
const fileName = getFileName(downloadUrl);
return storage
.bucket(fileBucket)
.file(fileName)
.delete()
});

Can't download file using google cloud storage and Cloud Functions for Firebase

I am having the opposite as this issue:
issues deleting an image using Cloud Functions for Firebase and #google-cloud/storage
(for the record, I have tried all things suggested there).
Basically I have a known file path, then a cloud function triggered by a database event.
I can initialise a bucket, get a file as well as its name, but then when I try and download it I get API Error: not found.
Here is my code:
module.exports = (orgID, reportID) => {
const bucket = gcs.bucket("MY_PROJECT.appspot.com");
const filePath = `/safety_hotline/${orgID}/${reportID}`;
const file = bucket.file(filePath);
// the name is shown correctly in the console
console.log(file.name);
const tempLocalFile = path.join(os.tmpdir(), filePath);
const tempLocalDir = path.dirname(tempLocalFile);
return mkdirp(tempLocalDir)
.then(() => {
// Download file from bucket.
return file.download({ destination: tempLocalFile });
})
.then(() => {
console.log("file downloaded succesfully");
})
.catch(err => {
console.log(err);
});
}
You can see I get the console log of the file name, so I don't understand why I can't then download it?
Any advice would be amazing, thanks!
Edit: edited code a bit for clarity
I see you have this line:
const filePath = `/safety_hotline/${orgID}/${reportID}`;
I am guessing that you may have named your objects with the pattern safety_hotline/org/report, but as written above the first character of the object name would be a slash. That's also a legal object name but it's usually unintentional. Try removing the slash?
You Try This Follow functions-samples ?
i'am try this follow done Download file successful

How to call refFromURL in Firebase Cloud Function

I'm storing references to files in Firebase Cloud Storage using URLs. In firebase client code, you can call firebase.storage().refFromURL(photo.image) to get the actual storage reference and do handy things like call delete with it. How do I accomplish the same thing in a cloud function (specifically a realtime database trigger)? I want to be able to clean up images after deleting the object that references them.
Following Bob Snider's answer, this is a little function (typescript) to extract file full path from URL.
export const getFileFromURL = (fileURL: string): Promise<any> => {
const fSlashes = fileURL.split('/');
const fQuery = fSlashes[fSlashes.length - 1].split('?');
const segments = fQuery[0].split('%2F');
const fileName = segments.join('/');
return fileName;
}
In a cloud function, to delete a file from storage you need the file's bucket name and file name (which includes the path). Those can be obtained on the client side from the storage reference. For example, a JS Storage Reference has properties bucket and fullPath. The string representation of a storage reference has format: gs://example-12345.appspot.com/path/to/file, where the bucket is example-12345.appspot.com and the file "name" is path/to/file.
In the example cloud function shown below, the client is expected to provide the bucket and filename as children of the trigger location. You could also write the URL string to the trigger location and then split it into bucket and filename components in the cloud function.
This code is based on the example in the Cloud Storage guide.
const functions = require('firebase-functions');
const gcs = require('#google-cloud/storage')();
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.deleteFile = functions.database.ref('/test').onWrite(event => {
const bucket = event.data.child('bucket').val();
const filename = event.data.child('filename').val();
console.log('bucket=', bucket, 'filename=', filename);
return gcs.bucket(bucket).file(filename).delete().then(() => {
console.log(`gs://${bucket}/${filename} deleted.`);
}).catch((err) => {
console.error('ERROR:', err);
});
});
Here is a one-liner.
const refFromURL = (URL) => decodeURIComponent(URL.split('/').pop().split('?')[0])
I've wrote code sample which I using instead refFromURL method from web-firebase in my functions project based on Bob Snyder answer.
function refFromUrl(gsLink) {
var fileEntryTemp = gsLink.file.replace("gs://", "")
var bucketName = fileEntryTemp.substring(0, fileEntryTemp.indexOf("/"));
var filename = gsLink.file.match("gs://" + bucketName + "/" + "(.*)")[1];
var gsReference = admin.storage().bucket().file(filename);
return gsReference;
}
Here is an example how I get a download link based on this ref:
var gsReference = refFromUrl(fileEntry);
gsReference.getSignedUrl({
action: 'read',
expires: '03-09-2491'
}).then(function (url) {
console.log(url);
response.send(url);
}).catch(function (error) {
});
Hope this will save time for somebody
For complicated actions on your database from cloud functions you could use Admin SDK https://firebase.google.com/docs/database/admin/startFor the usage of Cloud Storage in Cloud Function check this out https://firebase.google.com/docs/functions/gcp-storage-eventsCloud Functions may not provide the same capability as client since Cloud Functions is beta for now and people are still working on it.

Resources