2016-05-20 4 views
1

Используя firebase 3.0.x, можно ли сохранить изображение с кодировкой base64 в новую службу хранения Firebase?Сохраните кодированное изображение base64 в хранилище Firebase

Я использую canvas для изменения размера изображений в браузере перед их загрузкой и вывода их как base64 jpeg. Я знаю, что Storage api может принимать Blobs, но поддержка IE9 необходима для моего текущего проекта.

ответ

2

Последняя версия Firebase S DK поддерживает загрузку изображений base64. Просто используйте метод putString из хранилища Firebase.

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

Один маленький нюанс в том, что иногда вы будете иметь base64 строки с ненужными пробелами. Например, я обнаружил, что плагин Camera Cordova возвращает base64 с ненужными пробелами. SDK хранилища не сможет загрузить его, потому что JavaScript не может выполнить свою собственную функцию atob - что-то, что Firebase JS делает под капотом. Вам нужно будет удалить пробелы - см. DOM Exception 5 INVALID CHARACTER error on valid base64 image string in javascript

2

Если вы используете 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().

+0

Мне жаль, что я не могу использовать .toBlob, но он не поддерживается вообще Safari или IE <10. IE9 также не поддерживается полиполнением. –

+0

Вы также можете преобразовать b64 в blob вручную, см. Мой ответ. – Hobbyist

1

Вот два значения, которые я использую, чтобы помочь с поддержкой на .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); 
    }; 

Я использую этот метод, чтобы получить значение 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 
     } 
    } 
    } 

Incase вам интересно, 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

1

Да, теперь это возможно. Вы должны использовать новый метод Firebase Storage под названием putString. Вы можете прочитать спецификацию 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 строки: «хранения/invalid-format ", сообщение:" Firebase Storage: String не соответствует формату 'base64': Неверный символ найден ". Решение состоит в том, чтобы отрезать начало строки data:image/jpeg;base64, и использовать первый метод вместо putString(message, 'base64'). Тогда это работает.

+0

Я решил эту проблему с помощью addin: let file = image.split (',') [1] storeRef (файл, 'base64', {contentType: 'image/png'}); // принимать только данные изображения –

1

Вам нужно использовать функцию putString без преобразования BASE64 в blob.

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

Убедитесь, что передать метаданные {CONTENTTYPE: 'изображение/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() и/или поставить в качестве ЦСИ к <img> тега.

Смежные вопросы