具有流存档的 Websockets



这就是我正在使用的设置:

  1. 我在一个快速服务器上,它必须将存档的二进制有效负载流式传输到浏览器(无论是ziptar还是tar.gz - 尽管zip会很好)。
  2. 在这台服务器上,我
  3. 打开了一个 websocket,它连接到另一台服务器,该服务器正在向我发送目录中单个文件的二进制有效负载。我将这些有效负载逐个流式传输为缓冲区,并且我正在串行执行此操作(也就是说 - 逐个文件 - 一次没有打开多个 websocket,每个文件有一个 websocket)。这是我正在使用的websocket库:https://github.com/einaros/ws

我想遍历每个文件,打开一个 websocket,然后在缓冲区通过 websocket 时将缓冲区附加到存档器。将数据附加到存档器时,如果我可以将存档器的输出流式传输到浏览器(通过带有 response.writeresponse 对象),那就太好了。所以,基本上,当我从 websocket 获取有效负载时,我希望该有效负载通过存档器流式传输,然后传输到响应。:-)

我研究过的一些事情:

  1. node-zipstream - 这很好,因为它给了我一个输出流,我可以直接通过管道传输到response.write。但是,它似乎不支持嵌套文件/文件夹,更重要的是,它只接受输入流。我已经查看了源代码(非常简洁且可读),似乎如果我能够访问ZipStream.prototype.addFile中的update函数,当我从 websocket 获取二进制缓冲区时,我可以每次在 message 事件上调用它。不过,这非常混乱/笨拙,而且,鉴于该库似乎已经不支持嵌套文件/文件夹,我不确定我会使用它。
  2. node-archiver - 这与node-zipstream(可能是因为它受到它的启发)存在相同的问题,它允许我通过管道输出,但我无法为存档中的同一文件附加多个缓冲区(然后手动发出信号当最后一个缓冲区已附加到给定文件)。但是,它确实允许我拥有嵌套文件夹,这显然是 node-zipstream 的胜利。

有什么我不知道的事情,还是这只是我想做的一件非常疯狂的事情?

我目前看到的唯一选择是等待整个有效负载通过 websocket 流式传输,然后附加节点存档器,但我真的很想获得真正的流式传输/即时存档的好处。

我还考虑过创建各种读取流的可能性,只是为了充当代理对象,我可以将其传递到 node-archiver 中,然后将我从 websocket 获得的缓冲区附加到此读取流中。查看各种读取流,我不确定如何做到这一点。我能想到的唯一方法是创建一个写入流,向其输送缓冲区,并从该写入流中读取读取流。我在这里的思维过程正确吗?

与往常一样,感谢您为SO社区提供的任何帮助/指导。

编辑

由于我刚刚打开了这个问题,而且我是 node 的新手,因此可能有比我提供的答案更好的答案。我将保持这个问题开放,如果有人在几天内出现,我会接受更好的答案。与往常一样,我会对任何其他答案投赞成票,即使它们很荒谬,只要它们是正确的,并允许我像我一样即时流式传输。

我想出了一种方法来让它与节点存档器一起工作。

它基于我创建某种临时"代理流"的预感,灵感来自这个 SO 问题:如何在 Node.Js 中从字符串创建流?

基本要点是(咖啡脚本语法):

archive = archiver 'zip'
archive.pipe response // where response is the http response
// and then for each file...
fileName = ... // known file name
fileSize = ... // known file size
ws = .... // create websocket
proxyStream = new Stream()
numBytesStreamed = 0
archive.append proxyStream, name: fileName
ws.on 'message', (dataBuffer) ->
    numBytesStreamed += dataBuffer.length
    proxyStream.emit 'data', dataBuffer
    if numBytesStreamed is fileSize
        proxyStream.emit 'end'
        // function/indicator to do this for the next file in the folder
// and then when you're completely done...
archive.finalize (err, bytesOfArchive) ->
    if err?
        // do whatever
    else
        // unless you somehow knew this ahead of time
        res.addTrailers
            'Content-Length': bytesOfArchive
        res.end()

请注意,这不是我实现的完整解决方案。仍然有很多逻辑来处理获取文件、它们的路径等。更不用说错误处理了。

编辑

由于我刚刚打开了这个问题,而且我是节点的新手,因此可能会有更好的答案。我将保持这个问题开放,如果有人在几天内出现,我会接受更好的答案。与往常一样,我会对任何其他答案投赞成票,即使它们很荒谬,只要它们是正确的,并允许我像我一样即时流式传输。

相关内容

  • 没有找到相关文章

最新更新