【问题标题】:node.js Transfer and saving files using TCP Servernode.js 使用 TCP Server 传输和保存文件
【发布时间】:2017-09-04 00:35:10
【问题描述】:

我有很多设备将消息发送到用节点编写的 TCP 服务器。 TCP 服务器的主要任务是将其中一些消息路由到 redis,以便由另一个应用程序处理。

我编写了一个简单的服务器,可以很好地完成这项工作。代码的结构基本是这样的(不是实际代码,细节隐藏):

const net = require("net");

net.createServer(socket => {
  socket.on("data", buffer => {
    const data = buffer.toString();
    if (shouldRouteMessage(data)) {
      redis.publish(data);
    }
  });
});

大多数消息类似于:{"text":"message body"}{"lng":32.45,"lat":12.32}。但有时我需要处理像{"audio":"...encoded audio..."} 这样跨越多个“数据”事件的消息。

在这种情况下,我需要将编码的音频保存到文件中并发送到 redis {"audio":"path/to/audio-file.mp3"},其中路由是接收到音频数据的文件。

一个简单的选择是存储缓冲区,直到我检测到消息的结尾,然后将它们全部保存到一个文件中,但这意味着,除其他外,我必须在保存到磁盘之前将文件保存在内存中。

我希望使用流和管道有更好的选择。有什么建议么? (一些代码示例,会很好)

谢谢

【问题讨论】:

    标签: javascript node.js sockets tcp


    【解决方案1】:

    我终于解决了,所以我在此处发布解决方案以用于文档目的(运气好的话,可以帮助其他人)。

    解决方案确实非常简单:只需打开文件的写入流并在收到数据包时写入数据包。像这样的:

    const net = require("net");
    const fs = require("fs");
    
    net.createServer(socket => {
      socket.on("data", buffer => {
        let file = null;
        let filePath = null;
        const data = buffer.toString();
    
        if (shouldRouteMessage(data)) {
          // just publish the message
          redis.publish(data);
        } else if (isAudioStart(data)) {
          // create a write stream to a file and write the first data packet
          filePath = buildFilePath(data);
          file = fs.createWriteStream(filePath);
          file.write(data);
        } else if (isLastFragment(data)) {
          // if is the last fragment, write it, close the file and publish the result
          file.write(data);
          file.close();
          redis.publish(filePath);
          file = filePath = null;
        } else if (isDataFragment(data)) {
          // just write (stream) it to file
          file.write(data);
        }
      });
    });
    

    注意:shouldRouteMessagebuildFilePathisDataFragmentisLastFragment 是取决于数据类型的自定义函数。

    通过这种方式,传入的数据直接到文件中,无需之前将内容保存在内存中。节点的流摇滚!

    一如既往,魔鬼在细节中。一些检查是必要的,例如,确保在您想要写入文件时始终有一个文件。还要记住在转换为字符串时设置正确的编码(例如:buffer.toString('binary'); 对我有用)。根据您的数据格式,shouldRouteMessageisAudioStart... 和所有这些自定义函数可能或多或少复杂。

    希望对你有帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-07-26
      • 2015-03-06
      • 2012-09-03
      • 2018-02-14
      • 2012-05-28
      • 2021-02-08
      • 2014-04-15
      • 1970-01-01
      相关资源
      最近更新 更多