javascript - xhr - responsetype header
Mostrar imagen de blob usando javascript y websockets (5)
Actualmente estoy trabajando en una aplicación WebSocket que muestra imágenes enviadas por un servidor C ++. He visto un par de temas por ahí pero parece que no puedo deshacerme de este error en Firefox:
Imagen dañada o truncada: datos: imagen / png; base64, [algunos datos]
Aquí está el código Javascript que estoy usando para mostrar mi 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);
}
Estoy usando la imagen de un punto rojo que encontré en este tema: https://stackoverflow.com/a/4478878/1464608 Y la clase Base64 es de aquí: https://stackoverflow.com/a/246813/1464608
Pero el resultado de la base64 que obtengo no coincide y Firefox me recupera un error de la imagen dañada.
Sé que esto no es mucha información, pero no tengo ni idea de dónde buscar: / ¡Cualquier ayuda es más que bienvenida!
Creo que la solución más limpia sería cambiar el codificador base64 para que funcione directamente en un Uint8Array en lugar de una cadena.
Importante: para ello deberá establecer el tipo binario del socket web en "arraybuffer".
El método onmessage debería verse así:
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);
};
El codificador convertido debería tener este aspecto (basado en https://.com/a/246813/1464608 ):
// 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;
}
Gracias a las otras respuestas, logré recibir una imagen jpeg por websocket y mostrarla en una nueva ventana:
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'');
};
Gracias, está funcionando muy bien !!
Así que imagino que compartiría mi código javascript final:
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);
}
realmente no entiendo por qué la versión de blob es tan complicada, ¡pero esto hizo el truco!
Otra alternativa
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;
};
Puedes escribirlo mucho más simple:
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);
};