Подтвердить что ты не робот

Отображать изображение из 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 возвращает мне ошибку поврежденного изображения.

Я знаю, что это не много информации, но у меня нет подсказки, где искать:/ Любая помощь более чем приветствуется!

4b9b3361

Ответ 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');
                };