Ich arbeite derzeit an einer WebSocket-Anwendung, die von einem C++ - Server gesendete Bilder anzeigt. Ich habe dort ein paar Themen gesehen, aber ich kann diesen Fehler in Firefox scheinbar nicht beseitigen:
Bild beschädigt oder abgeschnitten: data: image/png; base64, [einige Daten]
Hier ist der Javascript-Code, mit dem ich meinen Blob anzeige:
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);
}
Ich verwende das Bild eines roten Punkts, das ich zu diesem Thema gefunden habe: https://stackoverflow.com/a/4478878/1464608 Und die Base64-Klasse ist von hier: https : //stackoverflow.com/a/246813/1464608
Aber das Base64-Ergebnis, das ich erhalte, stimmt nicht überein und Firefox meldet mir einen Fehler, dass das Image beschädigt ist.
Ich weiß, dass dies nicht viele Informationen sind, aber ich habe keine Ahnung, wo ich suchen soll:/Jede Hilfe ist mehr als willkommen !!
Ich denke, die sauberste Lösung wäre, den Base64-Encoder so zu ändern, dass er direkt auf einem Uint8Array anstelle eines Strings funktioniert.
Wichtig: Dazu müssen Sie den binaryType des Web-Sockets auf "arraybuffer" setzen.
Die onmessage-Methode sollte folgendermaßen aussehen:
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);
};
Der konvertierte Encoder sollte dann folgendermaßen aussehen (basierend auf https://stackoverflow.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;
}
Danke, es funktioniert super !!
Also denke ich, ich würde meinen endgültigen Javascript-Code teilen:
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);
}
ich verstehe nicht wirklich, warum die Blob-Version so trickreich ist, aber das hat es geschafft!
Sie können es viel einfacher schreiben:
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);
};
Eine andere Alternative
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;
};
Dank der anderen Antworten konnte ich ein JPEG-Bild per Websocket empfangen und in einem neuen Fenster anzeigen:
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');
};