将 base64 编码的图像保存到 Firebase 存储
Save base64 encoded image to Firebase Storage
使用 firebase 3.0.x,是否可以将 base64 编码的图像保存到新的 Firebase 存储服务中?
我正在使用 canvas 在上传图像之前在浏览器中调整图像大小,并将它们输出为 base64 jpeg。我知道存储 api 可以接受 Blob,但我当前的项目需要 IE9 支持。
如果您使用 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()
。
这是我用来帮助支持 .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);
};
我在必要时使用此方法直接获取 link 的 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
最新版Firebase SDK支持base64图片上传。只需使用 Firebase Storage 中的 putString
方法。
https://firebase.google.com/docs/reference/js/firebase.storage
一个小警告是,有时您的 base64 字符串会带有不必要的空格。例如,我发现 cordova Camera 插件 returns base64 带有不必要的空格。 Storage SDK 将无法上传此文件,因为 JavaScript 无法执行其本机 atob
功能 - Firebase JS 在幕后执行的操作。您必须去除空格 - 请参阅 DOM Exception 5 INVALID CHARACTER error on valid base64 image string in javascript
是的,现在可以了。您应该使用名为 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')
returns 关于格式错误的 Base64 字符串代码的错误:"storage/invalid-format",消息:"Firebase Storage: String does not match format 'base64': Invalid character found"。解决方案是切断字符串 data:image/jpeg;base64,
的开头并使用第一种方法代替 putString(message, 'base64')
。然后就可以了。
只需要使用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() and/or 以作为 src 放入 <img>
标签。
此解决方案适用于我使用 Google 云存储 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()
}
}
}
, () => { })
使用适用于网络的 Firebase SDK 9(截至 2022 年 5 月)
import { getStorage, ref, uploadString } from "firebase/storage";
const storage = getStorage();
const storageRef = ref(storage, 'some-child');
// Data URL string
const message4 = 'data:text/plain;base64,5b6p5Y+344GX44G+44GX44Gf77yB44GK44KB44Gn44Go44GG77yB';
uploadString(storageRef, message4, 'data_url').then((snapshot) => {
console.log('Uploaded a data_url string!');
});
使用 firebase 3.0.x,是否可以将 base64 编码的图像保存到新的 Firebase 存储服务中?
我正在使用 canvas 在上传图像之前在浏览器中调整图像大小,并将它们输出为 base64 jpeg。我知道存储 api 可以接受 Blob,但我当前的项目需要 IE9 支持。
如果您使用 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()
。
这是我用来帮助支持 .toBlob()
的两个值,它的性能较差,但是可以完成工作。
此方法接受 base64 字符串、内容类型 (IE: image/png)
以及使用 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);
};
我在必要时使用此方法直接获取 link 的 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
最新版Firebase SDK支持base64图片上传。只需使用 Firebase Storage 中的 putString
方法。
https://firebase.google.com/docs/reference/js/firebase.storage
一个小警告是,有时您的 base64 字符串会带有不必要的空格。例如,我发现 cordova Camera 插件 returns base64 带有不必要的空格。 Storage SDK 将无法上传此文件,因为 JavaScript 无法执行其本机 atob
功能 - Firebase JS 在幕后执行的操作。您必须去除空格 - 请参阅 DOM Exception 5 INVALID CHARACTER error on valid base64 image string in javascript
是的,现在可以了。您应该使用名为 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')
returns 关于格式错误的 Base64 字符串代码的错误:"storage/invalid-format",消息:"Firebase Storage: String does not match format 'base64': Invalid character found"。解决方案是切断字符串 data:image/jpeg;base64,
的开头并使用第一种方法代替 putString(message, 'base64')
。然后就可以了。
只需要使用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() and/or 以作为 src 放入 <img>
标签。
此解决方案适用于我使用 Google 云存储 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()
}
}
}
, () => { })
使用适用于网络的 Firebase SDK 9(截至 2022 年 5 月)
import { getStorage, ref, uploadString } from "firebase/storage";
const storage = getStorage();
const storageRef = ref(storage, 'some-child');
// Data URL string
const message4 = 'data:text/plain;base64,5b6p5Y+344GX44G+44GX44Gf77yB44GK44KB44Gn44Go44GG77yB';
uploadString(storageRef, message4, 'data_url').then((snapshot) => {
console.log('Uploaded a data_url string!');
});