使用javascript和WebSocket显示blob中的图像 我正在研究一个WebSoCK应用程序,它显示C++服务器发送的图像。 我在那里看到了一些话题,但我似乎无法摆脱Firefox中的这个错误:

使用javascript和WebSocket显示blob中的图像 我正在研究一个WebSoCK应用程序,它显示C++服务器发送的图像。 我在那里看到了一些话题,但我似乎无法摆脱Firefox中的这个错误:,javascript,html,websocket,blob,filereader,Javascript,Html,Websocket,Blob,Filereader,图像损坏或被截断:数据:图像/png;base64[一些数据] 下面是我用来显示blob的Javascript代码: socket.onmessage = function(msg) { var blob = msg.data; var reader = new FileReader(); reader.onloadend = function() { var string = reader.result; var buffer = Ba

图像损坏或被截断:数据:图像/png;base64[一些数据]

下面是我用来显示blob的Javascript代码:

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);
}
我正在使用我在本主题中找到的一个红点的图像: Base64类来自这里:

但是我得到的base64结果不匹配,Firefox检索到一个图像被破坏的错误

我知道这些信息不多,但我不知道去哪里找:/
欢迎任何帮助

我认为最干净的解决方案是将base64编码器更改为直接在UInt8数组而不是字符串上操作

重要提示:为此,需要将web套接字的binaryType设置为“arraybuffer”

onmessage方法应如下所示:

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);
};
转换后的编码器应如下所示(基于):

//将Uint8Array编码为base64的公共方法
功能编码(输入){
var keyStr=“abcdefghijklmnopqrstuvxyzabefghijklmnopqrstuvxyz012456789+/=”;
var输出=”;
变量chr1,chr2,chr3,enc1,enc2,enc3,enc4;
var i=0;
while(i>2;
enc2=((chr1&3)>4);
enc3=((chr2&15)>6);
enc4=chr3&63;
if(isNaN(chr2)){
enc3=enc4=64;
}否则如果(isNaN(chr3)){
enc4=64;
}
输出+=按键字符(enc1)+按键字符(enc2)+
按键字符(enc3)+按键字符(enc4);
}
返回输出;
}

谢谢,它工作得很好

因此,我想与大家分享我的最终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版本如此棘手,但这确实奏效了

你可以写得简单得多:

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);
};
另一种选择

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;

};

多亏了其他答案,我成功地通过websocket接收到一幅jpeg图像,并将其显示在一个新窗口中:

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');
                };

使用Blob非常简单:

//小红点图像
const content=新的Uint8Array([137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 5, 0, 0, 0, 5, 8, 6, 0, 0, 0, 141, 111, 38, 229, 0, 0, 0, 28, 73, 68, 65, 84, 8, 215, 99, 248, 255, 255, 63, 195, 127, 6, 32, 5, 195, 32, 18, 132, 208, 49, 241, 130, 88, 205, 4, 0, 14, 245, 53, 203, 209, 142, 14, 31, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130]);
document.getElementById('my-img')。src=URL.createObjectURL(
新Blob([content.buffer],{type:'image/png'}/*(1)*/)
);

应该显示一个小红点:
也许你可以尝试在别处解码你的编码图像,以确保你的编码/解码方法正确。尝试将
Base64.encode(string)
的结果与
btoa(string)进行比较
。对于高值字节,大多数base64库的运行方式与btoa有所不同;也许这是您的问题?我已经尝试过btoa()我发现了链接:声明WebSooCK不能发送图像或任何其他东西,而不是二进制数据。所以我将C++中的二进制数据转换成Base64,这样就可以让我的图像在Firefox中正确显示。但是,图像大小更大30%!使用WebSocket直接发送PNG图像真的不可能吗?顺便问一下,图像不是二进制数据吗?(如果这是一个愚蠢的问题,请道歉:o))问题是将二进制数据转换为(字符)字符串,根据使用的字符编码提供不同的结果。它可能适用于ISO-8859-1,因为所有代码点都映射到相应的unicode代码点。对于UTF-8,可能会出现问题,因为输入中的两个或多个字节可能会被解码为单个字符,而某些字节值可能是非法的UTF-8代码点。谢谢。这确实是一个很好的解决方案。对我来说,我必须添加Base64编码。我的返回类型看起来像:return“data:image/jpg;Base64”+output;对我不起作用。但是,在我删除
var bytes…
var blob…
行,然后更改
reader.readAsDataURL(blob)之后,它确实起作用了;
读卡器.readAsDataURL(arrayBuffer)
-这更简单。@Headcrab您使用哪种浏览器?Windows 10上的Firefox 48.0.2和Internet Explorer 11。在同一操作系统上的Edge浏览器中,您的版本和我的版本都不起作用。Chrome也一样。不知道这是否重要,但html文件不是由我的测试服务器提供的,我直接从同一台机器的硬盘打开它,例如。g、 像file:///C:/blahblah/client.html,然后它与用python编写的测试服务器建立websocket连接,该服务器以二进制模式读取PNG文件并按原样提供。如果您正在构建单页应用程序,请不要忘记释放URL以避免浪费内存:
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');
                };