将 base64 编码图像保存到 Firebase 存储
Posted
技术标签:
【中文标题】将 base64 编码图像保存到 Firebase 存储【英文标题】:Save base64 encoded image to Firebase Storage 【发布时间】:2016-09-18 02:01:56 【问题描述】:使用 firebase 3.0.x,是否可以将 base64 编码图像保存到新的 Firebase 存储服务?
我在上传之前使用画布在浏览器中调整图像大小,并将它们输出为 base64 jpeg。我知道 Storage api 可以接受 Blob,但我当前的项目需要 IE9 支持。
【问题讨论】:
***.com/questions/52157253/…中提供了对我有用的解决方案 【参考方案1】:您只需要使用 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”?这是什么物体? @odedbartov 那是 firebase 实例【参考方案2】:最新版本的 Firebase SDK 支持 base64 图片上传。只需使用 Firebase Storage 中的 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
【讨论】:
我应该在哪里使用 putString 方法? firebase-admin 没有它【参考方案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')
。然后它工作。
【讨论】:
我通过 addin 解决了这个问题: let file = image.split(',')[1] storeRef(file,'base64', contentType:'image/png'); //只取图像数据 你从哪里得到第一个对象'ref'?这是什么物体?【参考方案4】:如果您使用 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,但 Safari 或 IE 您也可以手动将 b64 转换为 blob,请参阅我的回答。【参考方案5】:以下是我用来帮助支持.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
【讨论】:
【参考方案6】:此解决方案适用于我使用 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()
, () => )
【讨论】:
但是你如何得到'ref'呢?我为此奋斗了很长时间const contents = new Uint8Array(Buffer.from(base64ImgStr, 'base64'))
很重要。我做了contents=base64ImgStr
,但没有用。以上是关于将 base64 编码图像保存到 Firebase 存储的主要内容,如果未能解决你的问题,请参考以下文章
将base64字符串编码的图像/字节图像作为图像在Flutter中用于Firebase ML Vision中进行处理
在 Django Rest Framework 中接收 Base64 编码的图像并保存到 ImageField