Ionic 3 + Firebase Storage Get Profile Image - javascript

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
}

Related

Firebase Storage (web) not working when files are uploaded from phone

I'm creating a website using Firebase. The user should be able to upload & update their profile picture, so long as it is <10mb, and is a .jpg, .png, or .gif file.
What is supposed to happen:
User uploads a valid image
Create or update a reference /users/{uid}/profileImage within Firebase Storage
Use the getDownloadURL() method to get the image's URL, and store it as text inside Firestore, under the user's profile information
Use that URL as the src of the profile picture.
When I try to do this on my computer (Windows 10), it works perfectly. However, when I try to do it on my phone (iPhone 8; iOS 14.7.1), it does not work. The image uploaded from the phone reaches the /users/{uid}/profileImage, but then it doesn't properly get the downloadURL due to permission problems, even though the user is authenticated on the phone browser, as required by the rules.
The following is the code to (1) get the file and (2) update the user's profile picture:
// Grab dp img and store it in file var
let file = {}
const chooseFile = (e) => {
// Get the file from local machine
file = e.target.files[0]
console.log(file )
}
// Store dp in storage as file, and db as link
const updateDp = (currentUser) => {
// Check if new dp has been added/exists.
if ("name" in file) {
// Check if uploaded file is an image
if (file.type !== "image/jpeg" && file.type !== "image/png" && file.type !== "image/gif") {
alert("You can only upload .jpeg, .jpg, .png and .gif under 10mb")
return
}
// Check image file size
if (file.size/1024/1024>10) {
alert("The image size must be under 10mb")
return
}
// Create storage ref & put the file in it
storage
.ref("users/" + currentUser.uid + "/profileImage")
.put(file)
.then(() => {
// success => get download link, put it in DB, update dp img src
storage
.ref("users/" + currentUser.uid + "/profileImage")
.getDownloadURL()
.then(imgURL => {
db
.collection("users")
.doc(currentUser.uid)
.set({
dp_URL: imgURL,
dp_URL_last_modified: file.lastModifiedDate
}, {
merge: true
})
document.querySelector("#nav_dp").src = imgURL;
})
console.log("success")
}).catch(() => {
console.log(error.message)
})
} else {
console.log("Empty/no file")
}
}
The following is my Firebase Storage Rules:
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /users/{uid}/{profileImage} {
allow read: if request.auth!=null;
allow write: if request.auth!=null && request.auth.uid == uid;
}
}
}
The security rules and code look fine to me except the console.log("success") will log before you get the downloadURL as getDownloadURL() returns a Promise. Try changing your function to an async function as shown:
// Store dp in storage as file, and db as link
const updateDp = async (currentUser) => {
// ^^^^^
// Check if new dp has been added/exists.
if ("name" in file) {
try {
// Check if uploaded file is an image
if (
file.type !== "image/jpeg" &&
file.type !== "image/png" &&
file.type !== "image/gif"
) {
alert("You can only upload .jpeg, .jpg, .png and .gif under 10mb");
return;
}
// Check image file size
if (file.size / 1024 / 1024 > 10) {
alert("The image size must be under 10mb");
return;
}
// Create storage ref & put the file in it
const userPicRef = storage.ref(
"users/" + currentUser.uid + "/profileImage"
);
await userPicRef.put(file);
console.log("Image uploaded")
// success => get download link, put it in DB, update dp img src
const imgURL = await UserPicRef.getDownloadURL();
console.log(`Image URL: ${imgURL}`)
await db.collection("users").doc(currentUser.uid).set(
{
dp_URL: imgURL,
dp_URL_last_modified: file.lastModifiedDate,
},
{
merge: true,
}
);
console.log("Document Added")
document.querySelector("#nav_dp").src = imgURL;
} catch (error) {
console.log(error);
}
} else {
console.log("Empty/no file");
}
};
Answering my own question.
Turns out, I was using file.lastModifiedDate, which is a depreciated method. It works on the Google Chrome app ran on Android, but not in iOS.
To fix it, I used file.lastModified instead.

DocuSign Api returning filebytes string, getting blank or corrupted file when try to convert to PDF

I'm working with the docusign api in order to get some documents from envelopes, I get all the info, but for the PDF download I get a "filebytes" string, and when trying to process it to download it, I get just a blank page (not sure if that's the expecting result since I'm using sandbox account). I'm doing all this from the client.
here's what I'm doing to process the string:
const pdfBlob = new Blob([Buffer.from(content)], {
type: 'application/pdf'
});
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(pdfBlob, filename);
resolve();
} else {
const tempLink = document.createElement('a');
const url = window.URL.createObjectURL(pdfBlob);
const clickEvent = new MouseEvent('click', {
'view': window,
'bubbles': true,
'cancelable': false
});
tempLink.href = url;
tempLink.target = '_blank';
tempLink.download = filename;
document.body.appendChild(tempLink);
tempLink.dispatchEvent(clickEvent);
setTimeout(() => {
document.body.removeChild(tempLink);
window.URL.revokeObjectURL(url);
resolve();
}, 100);
}
});
Any ideas?
Here is a blog post on this topic.
The Node.js code is this (you have to do this from server):
// You would need to obtain an accessToken using your chosen auth flow
let apiClient = new ApiClient(basePath);
let config = new docusign.Configuration(apiClient);
config.addDefaultHeader('Authorization', 'Bearer ' + accessToken);
let envelopesApi = new docusign.EnvelopesApi(config);
var accountId; // accountId for your DocuSign account
var envelopeId; // envelopeId that you are working on
// produce a ZIP file with all documents including the CoC
let results1 = await envelopesApi.GetDocument(accountId, envelopeId, 'archive', null);
// produce a PDF combining all signed documents as well as the CoC
let results2 = await envelopesApi.GetDocument(accountId, envelopeId, 'combined', null);
// produce a particular document with documentId '1'
let results3 = await envelopesApi.GetDocument(accountId, envelopeId, '1', null);
//TODO - use byte array to write or send the file for your use
If your code or this code returns an empty page, please confirm that you don't get it if you use the DocuSign web app, it's possible it is empty?
Please remember encoding, this is using 64 bit encoding to get bits in the REST API.

Firebase Storage - Get Download URL from Public Image

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.

How to get download image url from firebase storage state_changed event?

This code should work but no matter what i do, I cant seem to get the downloadURL.
I am using vue js. This is the code for file upload.
And below you can see the image that shows the console log. It saved the image successfully, only problem is I dont get downloadURL, there does not seem to be one.
// upload file
uploadFile(file, metadata) {
if(file === null) return false
let pathToUpload = this.currentChannel.id
// parent means Messages.vue getMessagesRef() that returns either public or private channel
let ref = this.$parent.getMessagesRef()
// getPath() refers to the path below
let filePath = this.getPath() + '/' + uuidV4() + '.jpg'
// upload file
this.uploadTask = this.storageRef.child(filePath).put(file, metadata)
// upload state
this.uploadState = "uploading"
// on upload state change
this.uploadTask.on('state_changed', snapshot => {
console.log('image uploaded/state_changed in storage: ', snapshot)
// Upload en cours
let percent = (snapshot.bytesTransferred / snapshot.totalBytes) * 100
// $("#uploadedFile").progress("set percent", percent)
$(".progress-bar").css("width", percent+'%')
}, error => {
// Error
this.errors.push(error.message)
this.uploadState = 'error'
this.uploadTask = null
}, () => {
// Upload finished
this.uploadState = 'done'
console.log('done upload')
// reset form
this.$refs.file_modal.resetForm()
// recover the url of file
let fileUrl = this.uploadTask.snapshot.downloadURL
console.log('downloadURL(snapshot) from firebase: ', this.uploadTask.snapshot)
// sendFileMessage() will pass file as parameter on upload
this.sendFileMessage(fileUrl, ref, pathToUpload)
})
},
Console.log() result:
Thanks for your help!
According to firebase document, you have to call uploadTask.snapshot.ref.getDownloadURL in completed callback
uploadTask.snapshot.ref.getDownloadURL().then(function(downloadURL) {
console.log('File available at', downloadURL);
});

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