Save base64 encoded image to Firebase Storage
Solution 1
The latest version of the Firebase SDK supports base64 image uploads. Simply use the putString
method from Firebase Storage.
https://firebase.google.com/docs/reference/js/firebase.storage
One small caveat is that sometimes you'll have a base64 String with unnecessary whitespace. For example, I've found that the cordova Camera plugin returns base64 with unnecessary whitespace. The Storage SDK will fail to upload this because JavaScript can't perform it's native atob
function - something the Firebase JS does under the hood. You'll have to strip the whitespace - see DOM Exception 5 INVALID CHARACTER error on valid base64 image string in javascript
Solution 2
You only need to use the putString function without converting the BASE64 to blob.
firebase.storage().ref('/your/path/here').child('file_name')
.putString(your_base64_image, ‘base64’, {contentType:’image/jpg’});
Make sure to pass the metadata {contentType:’image/jpg’} as the third parameter (optional) to the function putString in order for you to retrieve the data in an image format.
or simply put:
uploadTask = firebase.storage().ref('/your/path/here').child('file_name').putString(image, 'base64', {contentType:'image/jpg'});
uploadTask.on(firebase.storage.TaskEvent.STATE_CHANGED, // or 'state_changed'
function(snapshot) {
// Get task progress, including the number of bytes uploaded and the total number of bytes to be uploaded
var progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
console.log('Upload is ' + progress + '% done');
switch (snapshot.state) {
case firebase.storage.TaskState.PAUSED: // or 'paused'
console.log('Upload is paused');
break;
case firebase.storage.TaskState.RUNNING: // or 'running'
console.log('Upload is running');
break;
}
}, function(error) {
console.log(error);
}, function() {
// Upload completed successfully, now we can get the download URL
var downloadURL = uploadTask.snapshot.downloadURL;
});
You can then use the downloadURL to save to firebase.database() and/or to put as an src to an <img>
tag.
Solution 3
Yes, it's possible now. You should use Firebase Storage new method called putString
. You may read spec here.
So, Firebase spec says that you have now two methods to store Base64 string and Base64url string:
// Base64 formatted string
var message = '5b6p5Y+344GX44G+44GX44Gf77yB44GK44KB44Gn44Go44GG77yB';
ref.putString(message, 'base64').then(function(snapshot) {
console.log('Uploaded a base64 string!');
});
// Base64url formatted string
var message = '5b6p5Y-344GX44G-44GX44Gf77yB44GK44KB44Gn44Go44GG77yB';
ref.putString(message, 'base64url').then(function(snapshot) {
console.log('Uploaded a base64url string!');
})
From my experience, using putString(message, 'base64url')
constantly returns Error about bad formated Base64 string code: "storage/invalid-format", message: "Firebase Storage: String does not match format 'base64': Invalid character found". The solution is to cut off beginning of string data:image/jpeg;base64,
and use first method instead putString(message, 'base64')
. Then it works.
Solution 4
If you use canvas.toBlob()
you'll get the byte[]
that you need to pass into Firebase Storage.
Quick example:
function save() {
var canvas = document.getElementById("canvas");
canvas.toBlob(blob => {
var storage = firebase.app().storage().ref();
var name = id + "/" + (new Date()).getTime() + ".png";
var f = storage.child("drawings/" + name);
var task = f.put(blob);
task.on('state_changed', function(snapshot) {
}, function(error) {
console.error("Unable to save image.");
console.error(error);
}, function() {
var url = task.snapshot.downloadURL;
console.log("Saved to " + url);
var db = firebase.database();
var chats = db.ref().child("chats");
chats.child(id).child("drawingURL").set(url);
});
});
};
Otherwise you'll have to convert the base64 yourself, for example with atob()
.
Solution 5
This solution works for me using the Google Cloud Storage API.
But it should work also with the Firebase one by replacing the file.save with the ref put method.
const file = storage.file(file_path_in_gs)
const contents = new Uint8Array(Buffer.from(base64ImgStr, 'base64'))
file.save(contents,
{
contentType: img_type,
metadata: {
metadata: {
contentType: img_type,
firebaseStorageDownloadTokens: uuid()
}
}
}
, () => { })
Sebastian Sandqvist
Updated on June 08, 2020Comments
-
Sebastian Sandqvist about 4 years
Using firebase 3.0.x, is it possible to save a base64 encoded image to the new Firebase Storage service?
I am using canvas to resize images in the browser prior to uploading them, and output them as a base64 jpeg. I know that the Storage api can accept Blobs, but IE9 support is needed for my current project.
-
Sebastian Sandqvist about 8 yearsI wish I could use .toBlob, but it isn't supported at all by Safari or IE<10. Even the polyfill is not supported by IE9.
-
Hobbyist about 8 yearsYou could also convert the b64 to a blob manually, see my answer.
-
Miguel Peguero over 6 yearsI solved this issue by addin : let file = image.split(',')[1] storeRef(file,'base64', {contentType:'image/png'}); //take only the image data
-
oded bartov over 3 yearswhere did you get the first object 'firebase'? what is this object?
-
oded bartov over 3 yearswhere did you get the first object 'ref'? what is this object?
-
oded bartov over 3 yearswhere should i use the putString method? the firebase-admin don't has it
-
oded bartov over 3 yearsBut how do you get the 'ref' for this? i struggle for a long time about it
-
Niño Angelo Orlanes Lapura almost 3 years@odedbartov that's the firebase instance
-
Wilfred Almeida over 2 yearsThe
const contents = new Uint8Array(Buffer.from(base64ImgStr, 'base64'))
is important. I didcontents=base64ImgStr
and it didn't work.