如何通过 socket.io 将图像发送到服务器?

Posted

技术标签:

【中文标题】如何通过 socket.io 将图像发送到服务器?【英文标题】:How do I send image to server via socket.io? 【发布时间】:2020-04-16 02:30:58 【问题描述】:

我一直在努力解决这个问题,但找不到合适的解决方案。 我希望能够通过 socket.io emit 将图像上传到服务器,然后再将它们保存到 MongoDB 数据库中。我该怎么做呢?我见过有人用 base64 编码来做,但我不知道它是如何工作的,这个网站上还有其他问题询问关于通过 socket.io 从服务器向客户端发送图像,但没有关于这个。感谢所有帮助。

目标:将图片上传到socket.emit('image', someimagefile)或类似的服务器。

如果您能提供类似的方式将图像发送给客户,我将不胜感激。

【问题讨论】:

不要使用base64...没有意义。您所做的只是在大小上增加 33% 的开销,浪费 CPU 和内存使用,以实现零收益。 Web Sockets 和 Socket.IO 支持二进制传输。此外,为什么要通过 socket.IO 发送它?正常的 HTTP 请求可以正常工作。此外,虽然您可以将二进制数据推送到 MongoDB 数据库中,但它很少是最佳解决方案。最好将资产存储在磁盘上,这样您就可以使用普通的 CDN 提供它,而不是稍后提供。 另见socket io, node js, Simple example to send image/files from server to client 【参考方案1】:

如您所述,您可以使用FileReader.readAsDataURL 将图像转换为base64 并发送编码字符串,然后在服务器上对其进行解码:

document.getElementById('file').addEventListener('change', function() 

  const reader = new FileReader();
  reader.onload = function() 
    const base64 = this.result.replace(/.*base64,/, '');
    socket.emit('image', base64);
  ;
  reader.readAsDataURL(this.files[0]);

, false);
socket.on('image', async image => 
    const buffer = Buffer.from(image, 'base64');
    await fs.writeFile('/tmp/image', buffer).catch(console.error); // fs.promises
);

或者更好地使用FileReader.readAsArrayBuffer 来获取您将发送到服务器的字节数组。

document.getElementById('file').addEventListener('change', function() 

  const reader = new FileReader();
  reader.onload = function() 
    const bytes = new Uint8Array(this.result);
    socket.emit('image', bytes);
  ;
  reader.readAsArrayBuffer(this.files[0]);

, false);
socket.on('image', async image => 
    // image is an array of bytes
    const buffer = Buffer.from(image);
    await fs.writeFile('/tmp/image', buffer).catch(console.error); // fs.promises
);

从服务器接收:

// Server side
socket.emit('image', image.toString('base64')); // image should be a buffer
// Client side
socket.on('image', image => 
    // create image with
    const img = new Image();
    // change image type to whatever you use, or detect it in the backend 
    // and send it if you support multiple extensions
    img.src = `data:image/jpg;base64,$image`; 
    // Insert it into the DOM
);

【讨论】:

【参考方案2】:

我不知道是否有人在寻找它,但我可以通过 socket.io 发送媒体...这是代码:

// sending media from client side
$("#send_media").change(function (e) 
  var data = e.originalEvent.target.files[0];
  var reader = new FileReader();
  reader.onload = function (evt) 
    var msg = ;
    msg.file = evt.target.result;
    msg.fileName = data.name;
    socket.emit("base64 file", msg);
    console.log(msg)
  ;
  reader.readAsDataURL(data);
);
   
// showing media to ui 
socket.on("base64 image", (msg) => 
  console.log("as", msg);
  $(".messages")
    .append(`<img src=$msg.file  />`);

  scrollToBottom();
);

// sending media from server side
    socket.on("base64 file", function (msg) 
      console.log("received base64 file from server: " + msg.fileName);
      socket.username = msg.username;
      io.to(roomId).emit('base64 image', //exclude sender
      // io.sockets.emit(
      //   "base64 file", //include sender

        
          file: msg.file,
          fileName: msg.fileName,
        
      );
    );

【讨论】:

以上是关于如何通过 socket.io 将图像发送到服务器?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用socket.io发送multipart / form-data?

通过 socket.io 发送画布图像

如何将二进制数据从 Node.js socket.io 服务器发送到浏览器客户端?

通过 socket.io 1.0 实时音频

我可以通过socket.emit发送多少数据?

Socket.io 将数据发送到全局变量