Firebase Storage - Get Download URL from Public Image - javascript

I have the logic of an image uploaded from the Frontend -> I get a download URL and attach it to the users document via a function.
This is the current code:
export const newProfilePictureUploaded = functions.region('europe-west1').storage.object().onFinalize(async (object) => {
if (!object.contentType?.startsWith('image/')) return;
return admin.storage().bucket(object.bucket).file(object.name || '').makePublic().then(async data => {
const filename = object.name as string;
const splitName = filename.split('/');
const folderName = splitName[0];
if (folderName === 'profilePics') {
const uid = splitName[1].substring(0, splitName[1].indexOf('.'));
console.log(uid);
await updateUserAvatar(uid, 'https://storage.googleapis.com/' + object.bucket + '/' + object.name)
return;
}
console.log('No operation for folder ' + folderName);
return
})
})
Now the thing is the image is displayed on the URL, but even if the Image in the Storage Bucket is replaced, then URL still points to that old image. While it should be deleted and the new image should be in that path.
Why dont I use the .getSignedUrl() method? The URL I get back is too long specially for storing it in the RTDB, and the URL can be public so its really unoptimal for me to use that method.

Related

How to add data on nested array in Firestore with react-native

I would like to ask if is it possible to add data in a nested array.The result i want is this
But i get this when i add a new rating with the code i use
async function getAll(){
const userEmail= firebase.firestore().collection('users')
const snapshot=await userEmail.where('email','==',index.email).get()
if (snapshot.empty) {
console.log('No matching documents.');
return;
}
snapshot.forEach(doc => {
userEmail.doc(doc.id).set({userRatings2:firebase.firestore.FieldValue.arrayUnion({parking:[markerName]})},{merge:true})
userEmail.doc(doc.id).set({userRatings2:firebase.firestore.FieldValue.arrayUnion({rating:[currentRating]})},{merge:true})
console.log(userEmail.doc(doc.id));
});
}
getAll()
Unfortunately in Firebase Firestore you can't even change a simple Array value at a specific index. That means also that you can't save nested array values. You can read more about it on this answer.
The only way to do it is to download the whole Array make your modifications and save the whole array again to the databse. There is not much context of your app so I can't tell if that is a good solution for you. It depends how much data you have in the array.
I've managed to do it by using forEach function to an array of image path
const [imageUri, setImageUri] = useState([]);
const [uploading, setUploading] = useState(false);
const UploadImage = () => {
setUploading(true);
imageUri.forEach(async (image, index) => {
// setTransferred(0);
const pathToFile = image;
let filename = pathToFile.substring(pathToFile.lastIndexOf('-') + 1);
const extension = filename.split('.').pop();
const name = filename.split('.').slice(0, -1).join('.');
filename = name + Date.now() + '.' + extension;
const reference = storage().ref().child(`/userprofile/${filename}`);
// path to existing file on filesystem
// uploads file
const task = reference.putFile(pathToFile);
try {
await task;
const url = await reference.getDownloadURL();
downloadableURI.push(url);
if (index == imageUri.length - 1) {
setUploading(false);
Alert.alert(
'Image uploaded!',
'Your image has been uploaded to the Firebase Cloud Storage Successfully!',
);
}
} catch (e) {
console.log(e);
}
});
};
whenever the function is called, then the array of images is uploaded to firebase storage,

Firestorage has different behavior when hardcode

I don't know what happened with my code. But everytime i used this code is working
const downloadUrlThumb = async(urlPathThumbs) => {
const gsRef = projectStorage.refFromURL('gs://myapps.appspot.com/courses/m9APF8TEUnfS6IQew591sl4kphH2/thumbs/business-3560917_640_200x200.jpg') // hardcode mode
//const gsRef = projectStorage.refFromURL(urlPathThumbs)
await gsRef.getDownloadURL().then(urlDownload => {
console.log('URL THUMB ADALAH: ', urlDownload);
url.value = urlDownload
}).catch(err => {
console.log(err.message);
})
}
But when i switched to urlPathThumbs it will become error 404. Error said like so
Firebase Storage: Object
'courses/m9APF8TEUnfS6IQew591sl4kphH2/thumbs/Rectangle 68
(1)_200x200.png' does not exist. (storage/object-not-found)
however they both are same pattern. This is how variable urlPathThumbs created in previous snippet code
var filename = file.name.replace(/(\.[\w\d_-]+)$/i, '_200x200$1')
console.log('filename ', filename);
let location = 'gs://myapps.appspot.com/courses/'+user.value.uid+'/thumbs/'+filename
console.log('full location: ', location); // --> This will print full location: gs://myapps.appspot.com/courses/m9APF8TEUnfS6IQew591sl4kphH2/thumbs/Rectangle 68 (1)_200x200.png
await downloadUrlThumb(location)
this file is successful uploaded and i can see it in firebase storage location:
Please can somebody help me?
since refFromURL is expecting a URL string, spaces should not be allow. You will need to urlencode the spaces.
e.g.
console.log(encodeURI("gs://myapps.appspot.com/courses/m9APF8TEUnfS6IQew591sl4kphH2/thumbs/Rectangle 68 (1)_200x200.png"))
refFromURL refFromURL ( url : string ) : Reference Returns a
reference for the given absolute URL.
Parameters url: string A URL in the form: 1) a gs:// URL, for example
gs://bucket/files/image.png 2) a download URL taken from object
metadata. #see firebase.storage.FullMetadata.downloadURLs

How do I get access to the variables / methods in static files in Node.js + Expressjs at the server-side without using POST request?

More Specifically, I have a blob initialized and processed in a .js file in the 'public' (static folder) folder. Since that has been processed at the client-side, I want to know if there's a way I can somehow get access to the blob at the server-side without using a POST request. The file we talking about has been processed and is stored in a variable in a static file (script.js), Now I need to upload that variable/blob onto the Database. But, in a static file, I don't have access to the Database and can't even export the variable to the server. How do I get access to that variable which is within the static file? Someone, please edit if they have understood my requirement.
What my program does is that it records audio through the microphone of the client And that audio file has to be uploaded onto the Database. Now, I can add the functionality of 'Download' for the client and let the client download the file and then the client uses <input> tag to send a POST request to the server, But, now the client can upload any audio file into that input tag, Basically, this is a web app for live monitoring students writing exam, So that don't they don't cheat I capture their audio and save it to the DB. Please refer to my folder Structure for more details and then read the question again.
My Folder Structure:
--DBmodels
---AudioModels.js
---ImageModel.js
--node_modules
--public
---scipt.js (This contains the code for audio processing)
--views
---test.ejs (Main HTML page)
--index.js (server file)
--package.json
Here is a small diagram for reference :
Diagram
And here is my Folder Structure :
Folder Structure
One way of doing is this to download it on the client-side and then ask the client to upload but that doesn't work for me due to some reasons.
Here is my script.js, But I don't have access of the variables such as chunk_audio[] on the server.
const chunks_audio = [];
mediaRecorder.onstop = async function (e) {
console.log("DONE WITH AUDIO");
const blob = new Blob(chunks_audio, {
'type': "audio/ogg codecs=opus"
});
const audioURL = window.URL.createObjectURL(blob);
console.log(audioURL);
var link = document.getElementById("downloadaudio");
link.href = audioURL;
var audioMIMEtypes = ["audio/aac", "audio/mpeg", "audio/ogg", "audio/opus", "audio/wav"]
const audio = blob
const audiodb = new AudioSchema({
name : "Audio"+Date.now().toString()[5]
});
saveAudio(audiodb,audio)
try{
const new_audio = await audiodb.save();
console.log("AUDIO UPLOADED" + new_audio);
}catch (err){
console.log(err);
}
function saveAudio(audiodb, audioEncoded) {
if (audioEncoded == null) return;
console.log("before parse: " + audioEncoded);
const audio = JSON.parse(audioEncoded);
console.log("JSON parse: " + audio);
if (audio != null && audioMIMEtypes.includes(audio.type)) {
audiodb.audio = new Buffer.from(audio.data, "base64");
audiodb.audioType = audio.type;
}
}
// module.exports = chunks_audio; (This doesn't work for obvious reasons)
Here is my server file (index.js) , I tried to use POST request where the user posts the audio file after it gets downloaded, But the user could post any other file in the <input> tag, So that doesn't match with my requirement:
var audioMIMEtypes = ["audio/aac", "audio/mpeg", "audio/ogg", "audio/opus", "audio/wav"]
app.post('/', async ( req, res, next)=>{
const audio = blob // 'blob' is a variable in script.js , Hence don't have access here
const audiodb = new AudioSchema({
name : "Audio"+Date.now().toString()[5]
});
saveAudio(audiodb,audio)
try{
const new_audio = await audiodb.save();
console.log("AUDIO UPLOADED" + new_audio);
}catch (err){
console.log(err);
}
function saveAudio(audiodb, audioEncoded) {
if (audioEncoded == null) return;
console.log("before parse: " + audioEncoded);
const audio = JSON.parse(audioEncoded);
console.log("JSON parse: " + audio);
if (audio != null && audioMIMEtypes.includes(audio.type)) {
audiodb.audio = new Buffer.from(audio.data, "base64");
audiodb.audioType = audio.type;
}
}
})

Ionic 3 + Firebase Storage Get Profile Image

I have this code:
/////////////////////////////////////////////CROP + UPLOAD FOR FIREBASE STORAGE//////////////////////////
// Return a promise to catch errors while loading image
getMedia(): Promise<any> {
// Get Image from ionic-native's built in camera plugin
return Camera.getPicture(this.options)
.then((fileUri) => {
// Crop Image, on android this returns something like, '/storage/emulated/0/Android/...'
// Only giving an android example as ionic-native camera has built in cropping ability
if (this.platform.is('ios')) {
return fileUri
} else if (this.platform.is('android')) {
// Modify fileUri format, may not always be necessary
fileUri = 'file://' + fileUri;
/* Using cordova-plugin-crop starts here */
return Crop.crop(fileUri, { quality: 100 });
}
}).then((path) => {
// path looks like 'file:///storage/emulated/0/Android/data/com.foo.bar/cache/1477008080626-cropped.jpg?1477008106566'
// console.log('Cropped Image Path!: ' + path);
path; // return the path of file
window.resolveLocalFileSystemURL(path, FE=>{
FE.file(file=>{
const FR=new FileReader()
FR.onloadend = ((res: any)=>{
let AF=res.target.result
let blob=new Blob([new Uint8Array(AF)], {type: 'image/jpg'});
this.upload(blob)
});
FR.readAsArrayBuffer(file);
})
})
})
}
upload(blob:Blob){
const currentUserId = this.fire.auth.currentUser.uid; // get user UID in firebase
this.Fbref.child(`Profile/${currentUserId}/img`).put(blob); //path in firebase storage
////GET Image URL
this.Fbref.child(`Profile/${currentUserId}/img` ).getDownloadURL().then(function(url){
console.log("the URL Image is: " + url);
url;
let photoURL = this.url
});}
It is working perfectly, does the image cut and then upload .... but I am not able to save the URL of the image inside the user profile DOC in the Firestore database.
Need to put as photoURL: (URL Image)
Does anyone know how to do it?
[SOLVED]
Adding the code below worked perfectly
savephotoURL(){
const currentUserId = this.fire.auth.currentUser.uid;
this.Fbref.child(`Profile/${currentUserId}/img` ).getDownloadURL().then(function(url){
console.log("the URL Image is: " + url);
let imageURL = url
return imageURL
}).then((imageURL) => {
this.database.doc(`ProfileUser/${currentUserId}/`).update({photoURL:imageURL}) })// save url in Firestore database realtime
}

How to upload an array of images to firebase storage?

Rightnow i'm using a array.map method to upload each file and gets the url in response but the thing is it gives me "C:\fakepath\pic1" in some files which creates a messs although it uploads it correctly(means i've seen the images in my firebase storage) but not get back the url in response
This is the code i'm using to put files
uploadPicsArr.map(function (pic, index) {
var storageRef = fbStorage.ref('images/'+token+'/'+pic.name);
// Upload file to Firebase Storage
var uploadTask = storageRef.put(pic.file);
uploadTask.on('state_changed', null, null, function () {
var downloadUrl = uploadTask.snapshot.downloadURL;
userInfo[pic.name] = downloadUrl;
})
if (uploadPicsArr.length == index + 1) {
fbDatabase.ref('users').push(userInfo).then(function (success){
browserHistory.push('/home');
});
}
})
fbStorage: firebase.storage()
uploadPicsArr = an array of objects and every object has a property name and file
name: name of the selected file
file: selected file
Please tell me what i'm doing wrong or if there's any other better way to upload the whole array and get each file URL in response then it would be better
I think you forget to pass the snapshot as a parameter in the complete function:
uploadPicsArr.map(function (pic, index) {
var storageRef = fbStorage.ref('images/'+token+'/'+pic.name);
// Upload file to Firebase Storage
var uploadTask = storageRef.put(pic.file);
uploadTask.on('state_changed', null, null, function (snapshot) {
userInfo[pic.name] = snapshot.downloadURL;
})
if (uploadPicsArr.length == index + 1) {
fbDatabase.ref('users').push(userInfo).then(function (success){
browserHistory.push('/home');
});
}
})

Categories