【问题标题】:Can you pass meta data along with a stream?您可以将元数据与流一起传递吗?
【发布时间】:2013-09-10 06:30:52
【问题描述】:

当我通过流传输图像文件之类的东西时,有什么方法可以发送元对象吗?

我的服务器收到用户发送的图像。图像通过一组执行各种操作的流进行推送。

最终流发出data 事件,它将生成的图像缓冲区传递给回调,但我丢失了用户的所有上下文。我需要将生成的图像与用户的 id 和其他一些元数据联系起来。

理想:

stream.on('data', function(img, meta){
   ...
})

感谢任何可能的解决方案!

【问题讨论】:

  • 您应该提供更多详细信息,然后才能期望人们提供更好的答案..
  • 你能展示你尝试了什么吗?
  • 基本上,当你想要读取或写入任何不是字符串或缓冲区的对象时,你需要将你的流放入objectMode
  • 为什么要将生成的图像缓冲区传递给回调?听起来你做错了流
  • @JonathanOng 这就是我正在使用的库的方式。当你得到这一点时,它不是一个img缓冲区,它是一个opencv矩阵。

标签: node.js stream


【解决方案1】:

简而言之,不,Node.js 中没有内置任何内容来支持将元数据包含在流中。不过,您还有其他一些选择,包括:

  1. 您可以使用闭包将元数据与流分开跟踪。例如:

    function handleImage(imageStream) {
      var meta = {...};
      imageStream.pipe(otherStreams).on('data', function(image) {
         // you now have `image` and `meta` variables at your disposal here.
      }
    }
    

    这样做的缺点是您的otherStreams 无法使用元数据。

    如果您的其他流是您无法控制的第三方代码,或者他们不需要了解元数据,这是一个很好的解决方案。

  2. 您可以执行类似于 HTTP 标头的操作,其中直到某个点的所有数据都是元数据,之后的所有数据都是图像。 (在 HTTP 中,分隔符位于首先出现 \n\n 的位置。)链中的所有流都必须知道并处理它。

    如果您知道您的元数据将始终位于一个块中,并且您的任何流都不会拆分或合并块,那么您可以稍微简化一下,只需说第一个(或最后一个)块始终是元数据。

  3. 切换到像 Amoli 在他的回答中提到的对象流。在这里你会通过{image: imgData, meta: {...}}。然后,您必须更新您的其他流才能使用这种格式。

    不过,这种方法的主要缺点是,您要么必须多次传递元数据,将其缓存到需要它的每个流的某个位置,要么将整个图像作为一个块传递(哪种方式会扼杀整个点“流”)。而且,据我所知,node.js 可以比对象流更好地优化文本/二进制流。因此,对于您的情况,这可能不是一个好方法。

  4. https://github.com/dominictarr/mux-demux 在这里可能会有所帮助。它将多个流合并为一个,因此您可以拥有单独的图像和元流。不过,我不确定它对您的情况有多好。您可能需要更新所有信息流才能意识到这一点。

我知道我说过除了第一个选项之外的所有选项都需要修改其他流,但有一种解决方法:您可以创建一个通用的“流包装器”,将图像和元数据拆分并仅传递图像数据通过主流,并让元数据绕过它并继续到链的下一个。不过,这很快就会变得丑陋,所以可能不是最好的主意。

【讨论】:

  • 谢谢,一些选项的有用概述。 1: 如果没有其他可能,这就是我要尝试的。似乎这可能是要走的路。我将不得不看看我是否可以重新设计东西以将它们包含在同一个闭包中。 2: 这是一个好主意,但我将使用 3rd 方流,所以我认为它不会在这种情况下工作。 3: 就像你说的那样,这会杀死整个流点。如果我打算这样做,但需要流提供的优势,我会使用回调。 4: 很有趣,但我认为这对我的情况没有帮助。
  • 我看到了这个新想法,但似乎在尝试协调事物并将它们保持在一起而不等待每个流时可能会变得混乱。我认为实现1: 的问题是,每次将数据传递给它时,我都需要创建一个新流。不能保证data 会是我刚刚传入的图像。对吧?我将传输大量图像。
  • 是的,每个图像都需要新的流,但我相信这是标准做法。
【解决方案2】:

基本上,当您想要读取或写入任何不是字符串或缓冲区的对象时,您需要将您的流放入objectMode

示例 (source):

function S3Lister (s3, options) {
  options || (options = {});
  stream.Readable.call(this, { objectMode : true });

  this.s3 = s3; // a knox-like client.
  this.marker = options.start;
  this.connecting = false;
  this.ended  = false;
}

util.inherits(S3Lister, stream.Readable);

我们将流设置为使用 objectMode,因为我们不仅要返回数据,还要返回一些元数据。

更多信息:

【讨论】:

  • 我看到了这篇博文。我仍然想读取缓冲区,我只想随缓冲区发送一个元对象。
【解决方案3】:

我为这种类型的东西创建了一个名为metastream 的模块。 (在 npm 中)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-15
    • 2017-09-17
    相关资源
    最近更新 更多