Отображать изображение из blob с помощью javascript и websockets
В настоящее время я работаю над приложением WebSocket, которое отображает отправку изображений с сервера С++.
Я видел пару тем, но я не могу избавиться от этой ошибки в Firefox:
Изображение повреждено или усечено: data: image/png; base64, [некоторые данные]
Вот код Javascript, который я использую для отображения моего blob:
socket.onmessage = function(msg) {
var blob = msg.data;
var reader = new FileReader();
reader.onloadend = function() {
var string = reader.result;
var buffer = Base64.encode(string);
var data = "data:image/png;base64,"+buffer;
var image = document.getElementById('image');
image.src = data;
};
reader.readAsBinaryString(blob);
}
Я использую изображение красной точки, которое я нашел на эту тему: qaru.site/info/147341/...
И класс Base64 отсюда: qaru.site/info/5484/...
Но результат base64, который я получаю, не соответствует, и Firefox возвращает мне ошибку поврежденного изображения.
Я знаю, что это не много информации, но у меня нет подсказки, где искать:/
Любая помощь более чем приветствуется!
Ответы
Ответ 1
Я думаю, что самым чистым решением было бы изменить кодировщик base64 для работы непосредственно с Uint8Array вместо строки.
Важно. Для этого вам нужно установить для бинарного типа веб-сокета значение "arraybuffer".
Метод onmessage должен выглядеть следующим образом:
socket.onmessage = function(msg) {
var arrayBuffer = msg.data;
var bytes = new Uint8Array(arrayBuffer);
var image = document.getElementById('image');
image.src = encode(bytes);
};
Преобразованный кодировщик должен выглядеть так (на основе fooobar.com/questions/5484/...):
// public method for encoding an Uint8Array to base64
function encode (input) {
var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
var output = "";
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
var i = 0;
while (i < input.length) {
chr1 = input[i++];
chr2 = i < input.length ? input[i++] : Number.NaN; // Not sure if the index
chr3 = i < input.length ? input[i++] : Number.NaN; // checks are needed here
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
output += keyStr.charAt(enc1) + keyStr.charAt(enc2) +
keyStr.charAt(enc3) + keyStr.charAt(enc4);
}
return output;
}
Ответ 2
Спасибо, он отлично работает!!
Итак, я полагаю, что поделился бы своим последним кодом javascript:
var socket = new WebSocket('ws://'+host+':'+port, protocol);
socket.binaryType = 'arraybuffer';
try {
socket.onopen = function() {
document.getElementById('status').style.backgroundColor = '#40ff40';
document.getElementById('status').textContent = 'Connection opened';
}
socket.onmessage = function(msg) {
var arrayBuffer = msg.data;
var bytes = new Uint8Array(arrayBuffer);
var image = document.getElementById('image');
image.src = 'data:image/png;base64,'+encode(bytes);
}
socket.onclose = function(){
document.getElementById('status').style.backgroundColor = '#ff4040';
document.getElementById('status').textContent = 'Connection closed';
}
} catch(exception) {
alert('Error:'+exception);
}
не понимаю, почему версия blob настолько сложна, но это сделало трюк!
Ответ 3
Вы можете написать это намного проще:
socket.onmessage = function(msg) {
var arrayBuffer = msg.data;
var bytes = new Uint8Array(arrayBuffer);
var blob = new Blob([bytes.buffer]);
var image = document.getElementById('image');
var reader = new FileReader();
reader.onload = function(e) {
image.src = e.target.result;
};
reader.readAsDataURL(blob);
};
Ответ 4
Другая альтернатива
let urlObject;
socket.onmessage = function(msg) {
const arrayBuffer = msg.data;
const image = document.getElementById('image');
if (urlObject) {
URL.revokeObjectURL(urlObject) // only required if you do that multiple times
}
urlObject = URL.createObjectURL(new Blob([arrayBuffer]));
image.src = urlObject;
};
Ответ 5
Благодаря другим ответам мне удалось получить jpeg-образ через websocket и отобразить его в новом окне:
socket.binaryType = "arraybuffer";
socket.onmessage = function (msg)
{ var bytes = new Uint8Array(msg.data);
var blob = new Blob([bytes.buffer]);
window.open(URL.createObjectURL(blob),'Name','resizable=1');
};