使用firebase 3.0.x,是否可以将base64编码的图像保存到新的Firebase存储服务?
我使用画布在上传之前在浏览器中调整图像大小,并将它们输出为base64 jpeg。我知道Storage api可以接受Blob,但我目前的项目需要IE9支持。
答案 0 :(得分:6)
您只需使用 putString 功能,而无需将BASE64转换为blob。
firebase.storage().ref('/your/path/here').child('file_name')
.putString(your_base64_image, ‘base64’, {contentType:’image/jpg’});
确保将元数据 {contentType:'image / jpg'} 作为 第三个参数 (可选)传递给函数putString以便您以图像格式检索数据。
或简单地说:
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;
});
然后,您可以使用 downloadURL 保存到firebase.database()和/或将src作为<img>
标记。
答案 1 :(得分:3)
最新版本的Firebase SDK支持base64图片上传。只需使用Firebase存储中的putString
方法。
https://firebase.google.com/docs/reference/js/firebase.storage
有一点需要注意的是,有时候你会有一个带有不必要空格的base64字符串。例如,我发现cordova Camera插件返回base64,带有不必要的空格。 Storage SDK将无法上传此内容,因为JavaScript无法执行本机atob
功能 - 这是Firebase JS所做的事情。您必须删除空格 - 请参阅DOM Exception 5 INVALID CHARACTER error on valid base64 image string in javascript
答案 2 :(得分:3)
是的,现在可以。您应该使用名为putString
的Firebase存储新方法。您可以阅读规范here。
因此,Firebase规范说您现在有两种方法来存储Base64字符串和Base64url字符串:
// 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!');
})
根据我的经验,使用putString(message, 'base64url')
会不断返回关于格式错误的Base64字符串代码的错误: “storage / invalid-format”,消息:“Firebase存储:字符串与格式'base64不匹配':找到无效的字符“ 。解决方案是切断字符串data:image/jpeg;base64,
的开头,然后使用第一种方法putString(message, 'base64')
。然后它工作。
答案 3 :(得分:2)
如果您使用canvas.toBlob()
,则会获得需要传递到Firebase存储空间的byte[]
。
快速举例:
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);
});
});
};
否则你必须自己转换base64,例如使用atob()
。
答案 4 :(得分:1)
以下是我用来帮助.toBlob()
支持的两个值,但它的性能较差,但它可以完成工作。
此方法接受base64字符串,内容类型(IE: image/png)
以及使用atob()
构建blob时的回调
var b64_to_blob = function(b64_data, content_type, callback) {
content_type = content_type || '';
var slice_size = 512;
var byte_characters = atob(b64_data);
var byte_arrays = [];
for(var offset = 0; offset < byte_characters.length; offset += slice_size) {
var slice = byte_characters.slice(offset, offset + slice_size);
var byte_numbers = new Array(slice.length);
for(var i = 0; i < slice.length; i++) {
byte_numbers[i] = slice.charCodeAt(i);
}
var byte_array = new Uint8Array(byte_numbers);
byte_arrays.push(byte_array);
}
var blob = new Blob(byte_arrays, {type: content_type});
callback(blob);
};
我在必要时使用此方法获取直接链接的base64值。在我的情况下,它是在用户注册我的应用程序时下载用户的Facebook照片。
var image_link_to_b64 = function(url, content_type, callback) {
var image = new Image();
image.crossOrigin = 'Anonymous';
image.onload = function() {
var canvas = document.createElement('CANVAS');
var context = canvas.getContext('2d');
var data_url;
canvas.height = this.height;
canvas.width = this.width;
context.drawImage(this, 0, 0);
data_url = canvas.toDataURL(content_type);
data_url = data_url.substr(22);
callback(data_url);
canvas = null;
};
image.src = url;
};
下面是将信息添加到firebase存储时的外观
$fileService.image_link_to_b64(facebook_info.photoURL + '?width=512&height=512', 'image/png', function(b64) {
$fileService.b64_to_blob(b64, 'image/png', function(blob) {
$fileService.upload_user_photo(blob, 'image/png', function(url) {
// Firebase storage download url here
}
}
}
如果你想知道upload_user_photo只是上传到firebase存储:
var upload_user_photo = function(data, blob, callback) {
var upload_task = user_photo_reference.child('user_photo').put(data);
upload_task.on('state_changed', function(snapshot) {
}, function(error) {
alert('error: ', error);
}, function() {
callback(upload_task.snapshot.downloadURL);
});
};]
对于IE9,请参阅此polyfill:https://github.com/eligrey/Blob.js/blob/master/Blob.js
答案 5 :(得分:0)
该解决方案对我来说可以使用Google Cloud Storage API。
但它也可以通过使用ref put方法替换file.save与Firebase一起使用。
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()
}
}
}
, () => { })