使用 firebase 3.0.x,是否可以将 base64 编码图像保存到新的 Firebase 存储服务?
我在上传之前使用画布在浏览器中调整图像大小,并将它们输出为 base64 jpeg。我知道 Storage api 可以接受 Blob,但我当前的项目需要 IE9 支持。
使用 firebase 3.0.x,是否可以将 base64 编码图像保存到新的 Firebase 存储服务?
我在上传之前使用画布在浏览器中调整图像大小,并将它们输出为 base64 jpeg。我知道 Storage api 可以接受 Blob,但我当前的项目需要 IE9 支持。
您只需要使用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>
标签。
最新版本的 Firebase SDK 支持 base64 图像上传。只需使用putString
Firebase Storage 中的方法。
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
是的,现在有可能。您应该使用名为putString
. 你可以在这里阅读规范。
因此,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')
不断返回 Error about bad formated Base64 string code: "storage/invalid-format", message: "Firebase Storage: String does not match format 'base64': Invalid character found"。解决方案是切断字符串的开头 data:image/jpeg;base64,
并改用第一种方法putString(message, 'base64')
。然后它工作。
如果您使用canvas.toBlob()
,您将获得byte[]
需要传递到 Firebase 存储的内容。
快速示例:
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()
.
这是我用来帮助支持.toBlob()
它的两个值,但性能较差,但它可以完成工作。
此方法接受 base64 字符串、内容类型(IE: image/png)
和一个回调,用于构建 blob 时使用atob()
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
此解决方案适用于我使用 Google Cloud Storage API。
但它也应该与 Firebase 一起使用,方法是将 file.save 替换为 ref put 方法。
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()
}
}
}
, () => { })