web-dev-qa-db-ja.com

base64でエンコードされた画像をFirebaseStorageに保存します

Firebase 3.0.xを使用して、base64でエンコードされた画像を新しいFirebase Storageサービスに保存することはできますか?

アップロードする前に、キャンバスを使用してブラウザで画像のサイズを変更し、base64jpegとして出力しています。 Storage APIがBlobを受け入れることができることは知っていますが、現在のプロジェクトにはIE9のサポートが必要です。

6

Firebase SDKの最新バージョンは、base64イメージのアップロードをサポートしています。 FirebaseStorageのputStringメソッドを使用するだけです。

https://firebase.google.com/docs/reference/js/firebase.storage

小さな注意点の1つは、不要な空白を含むbase64文字列が存在する場合があることです。たとえば、cordovaCameraプラグインが不要な空白を含むbase64を返すことがわかりました。 JavaScriptはネイティブのatob関数を実行できないため、Storage SDKはこれをアップロードできません。これは、FirebaseJSが内部で実行する機能です。空白を削除する必要があります---を参照してください javascriptの有効なbase64画像文字列でのDOM例外5無効な文字エラー

5

BASE64をblobに変換せずに、putString関数を使用するだけで済みます。

firebase.storage().ref('/your/path/here').child('file_name')
.putString(your_base64_image, ‘base64’, {contentType:’image/jpg’});

メタデータを必ず渡してください{contentType: 'image/jpg'} as 3番目のパラメーター =(オプション)画像形式でデータを取得するための関数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>タグに配置したりできます。

はい、それは今可能です。 putStringというFirebaseStorageの新しいメソッドを使用する必要があります。仕様を読むことができます ここ

そのため、Firebaseの仕様では、Base64文字列とBase64url文字列を保存する方法が2つあるとされています。

_// 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')の最初のメソッドを使用することです。その後、それは動作します。

4

canvas.toBlob()を使用すると、Firebase Storageに渡す必要のある_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);
      });
    });
  };
_

それ以外の場合は、たとえば atob() を使用してbase64を自分で変換する必要があります。

2

.toBlob()のサポートを支援するために使用する2つの値を次に示します。パフォーマンスは低下しますが、作業は完了します。

このメソッドは、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については、次のポリフィルを参照してください: https://github.com/eligrey/Blob.js/blob/master/Blob.js

1
Hobbyist