Je travaille actuellement sur une application WebSocket qui affiche des images envoyées par un serveur C++. J'ai vu quelques sujets par là, mais je n'arrive pas à me débarrasser de cette erreur dans Firefox:
Image corrompue ou tronquée: données: image/png; base64, [certaines données]
Voici le code Javascript que j'utilise pour afficher mon 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);
}
J'utilise l'image d'un point rouge que j'ai trouvée sur ce sujet: https://stackoverflow.com/a/4478878/1464608 Et la classe Base64 est d'ici: https : //stackoverflow.com/a/246813/1464608
Mais le résultat en base64 que j'obtiens ne correspond pas et Firefox me récupère une erreur d'image corrompue.
Je sais que ce n'est pas beaucoup d'informations mais je n'ai aucune idée où chercher:/Toute aide est plus que bienvenue !!
Je pense que la solution la plus propre serait de changer l'encodeur base64 pour qu'il fonctionne directement sur un Uint8Array au lieu d'une chaîne.
Important: Pour cela, vous devez définir le type binaire du socket Web sur "arraybuffer".
La méthode onmessage devrait ressembler à ceci:
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);
};
L'encodeur converti devrait alors ressembler à ceci (basé sur 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;
}
Merci, ça marche très bien !!
Donc je pense que je partagerais mon code 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);
}
ne comprends pas vraiment pourquoi la version blob est si délicate, mais cela a fait l'affaire!
Vous pouvez l'écrire beaucoup plus simplement:
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);
};
Une autre 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;
};
Grâce aux autres réponses, j'ai réussi à recevoir une image jpeg par websocket et à l'afficher dans une nouvelle fenêtre:
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');
};