Websocket发送blob对象而不是字符串

Posted

技术标签:

【中文标题】Websocket发送blob对象而不是字符串【英文标题】:Websocket sending blob object instead of string 【发布时间】:2018-12-21 12:01:36 【问题描述】:

我能够以某种方式运行Websocket,但问题是它在我想发送文本时在on message 事件上向我发送对象blob。

这是我的 websocket 服务器代码:

const WebSocket = require('ws');
const wss = new WebSocket.Server( port: 8080 )

var sockets = [];

wss.on('connection', ws => 
    //var id = ws.upgradeReq.headers['sec-websocket-key'];
    //console.log("New connection id ::", id);
    //w.send(id);
    sockets.push(ws);
    console.log("New client connected"+ ws);

  ws.on('message', message => 

    console.log(`Received message => $message`)

    //var id = ws.upgradeReq.headers['sec-websocket-key'];
    //var mes = JSON.parse(message);

    //sockets[message.to].send(mes.message);
     // console.log('Message on :: ', id);
    //console.log('On message :: ', message);
    sockets.forEach(w=> 
        w.send(message);
    );
  )

  ws.send('Welcome by server!')
)

客户端代码摘录

connection.onmessage = (e) => 
  document.getElementById("ReceviedText").innerhtml += ("<li>" + e.data + "</li>");

   // ReceviedText
  console.log(e.data);
  console.log(e);

  var reader = new FileReader(e.data);
  console.log(reader.result);

  //console.log(reader.readAsText());
  console.log(reader.readAsText(e.data));


我发现我可以使用文件阅读器将 blob 转换为字符串,但它返回 null。

【问题讨论】:

你在哪里初始化连接服务器端? 【参考方案1】:

我对对象数组也有同样的问题。通过使用JSON.stringify 将数据转换为 JSON 字符串来修复它。在客户端可以通过JSON.parse获取数据。

服务器

sockets.forEach(w => 
  w.send(JSON.stringify(message));
);

客户

connection.onmessage = (message: object) => 
  console.log(JSON.parse(message['data']));

【讨论】:

【参考方案2】:

我已经解决了这个问题..:

//index.js (Server)

const express = require('express');
const http = require('http');
const WebSocket = require("ws");
const PORT = 3000;

const server = http.createServer(express);
const wss = new WebSocket.Server(server);

wss.on('connection',function connection(ws)
    ws.on('message',function incoming(message)
        console.log("Received: "+message);
        
        wss.clients.forEach(function each(client)
            if(client!==ws && client.readyState===WebSocket.OPEN)
            
                client.send(JSON.stringify(message));
            
        );
    );
);

server.listen(PORT,()=>console.log(`Server is listening to PORT $PORT`));
<!-- index.html page -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Client 1</title>
</head>
<body>
   <input type="text" name="messageBox" id="messageBox">
   <button type="button" id="sendBtn">Send</button>

   <div class="container">
       <div class="receive-message">
           <p id="message"></p>
       </div>
   </div>
</body>
<script type="text/javascript">

    var sendBtn = document.getElementById("sendBtn");
    var messageBox = document.getElementById("messageBox");

    var socket = new WebSocket("ws://localhost:3000");

    sendBtn.addEventListener("click",()=>
        let val = messageBox.value;
        socket.send(val);
    );

    socket.addEventListener("open",function(event)
        socket.send("Connected.....");
    );

    socket.addEventListener('message',function(event)
        var string_arr =JSON.parse(event['data']).data;
        var string = "";

        string_arr.forEach(element => 
            string+=String.fromCharCode(element);
        );
        
        console.log(string);
    );
</script>
</html>

【讨论】:

【参考方案3】:

当我通过 Firefox Web 套接字客户端扩展发送消息时,我遇到了同样的问题。 在服务器端,我通过使用 JSON.stringify 将数据转换为 JSON 字符串来修复它。在客户端,您可以使用 JSON.parse 获取数据。

服务器

wss.clients.forEach(function each(client) 
      if (client !== ws && client.readyState === WebSocket.OPEN) 
        console.log('data %s', data);
        // client.send(data);
        // this is to solve the issue where web socket client
        // send data as blob instead of string
        client.send(JSON.stringify(data));
      
    );

客户

ws.onmessage = (e) => 
      const arr = JSON.parse(e.data).data;
      let newData = '';
      arr.forEach((element) => 
        newData+=String.fromCharCode(element);
      );
      console.log('newData ', newData);
    ;

【讨论】:

【参考方案4】:

FileReader.readAsText() 是一个基于事件的 API,如 MDN 文档中所述。

所以你需要设置reader.onload:

  const reader = new FileReader();
  reader.onload = function(evt) 
    console.log(evt.target.result);
  ;
  reader.readAsText(e.data);

另外,Blob.text() 也可以使用。

websocket.addEventListener("message", e =>         
    e.data.text().then(txt=>console.log(txt))   
);

文档描述了这两者之间的区别:

Blob.text() 返回一个承诺,而 FileReader.readAsText() 是一个 基于事件的 API。 Blob.text() 始终使用 UTF-8 作为编码,而 FileReader.readAsText() 可以使用不同的编码,具体取决于 blob 的类型和指定的编码名称。

【讨论】:

【参考方案5】:

在服务器端

ws.on('message', function message(data, isBinary) 
    wss.clients.forEach(function each(client) 
        if (client !== ws && client.readyState === WebSocket.OPEN) 
            client.send(data,  binary: isBinary );
        
    );
);

在客户端

socket.addEventListener('message', (event, isBinary) => 
    console.log(event.data)
)

isBinary 参数为我解决了问题

【讨论】:

以上是关于Websocket发送blob对象而不是字符串的主要内容,如果未能解决你的问题,请参考以下文章

使用 websocket javascript 客户端发送文件

vue js中的axios将请求作为字符串而不是对象发送

在连接时发送 Websocket 参数但不发送查询字符串

为啥我们必须通过请求对数组而不是对象进行字符串化?

Firebase 函数接收对象而不是字符串

oracle中blob,clob,nclob主要区别是啥?