【问题标题】:JSZip in koa.js with streaming input/output带有流输入/输出的 koa.js 中的 JSZip
【发布时间】:2016-08-29 18:54:36
【问题描述】:

我正在考虑使用 JSZip 在来自各种下游文件的文件上创建一个 zip 文件。这是我正在尝试做的伪代码:

function* handler () {
    const ids = this.request.body.ids;

    const zip = new JSZip();
    for (let i = 0; i < ids; i++) {
        const r = yield request.get('/some/remote/service/' + ids[i]);
        zip.file(ids[i], r.body);
    }
    this.body = zip.nodeStream():
}  

但大概这将要求所有文件的内容一次在内存中,并且在所有文件下载之前不会开始流式传输。

我意识到我可以通过以下方式优化下载时间:

const allFiles = yield ids.map((id) => request.get('/some/remote/service/' + id));

for (let i = 0; i < ids.length; i++) zip.file(ids[i], allFiles[i]);

但主要是我希望有一种方法,一次只在内存中保存一个文件,并通过 zip 将结果流式传输回客户端。 JSZip 有可能吗?

【问题讨论】:

  • 您是否尝试将文件流式传输到客户端下载的.zip 文件中?
  • 它比我在这里表示的要复杂一些,但基本上在服务器端,特定 id 后面可能有 N 个文件,客户端应该收到一个包含所有文件的 zip 文件。在后端数据存储中,它们没有预压缩,所以我会即时进行。
  • 所以回答你的问题;是的,客户正在提供一个 id 并期待一个 zip 文件返回。
  • 我不确定 ZIP 是否是一种流格式(您可以将数据连接到输出流),这将是您尝试做的要求。

标签: javascript node.js koa jszip


【解决方案1】:

我希望有一种方法可以一次只在内存中保存一个文件,然后通过 zip 将结果流式传输回客户端。 JSZip 有可能吗?

并非没有缺点。 JSZip 不接受 (yet) 生成器或函数作为文件的内容。它期望文件的全部内容、它的承诺或流。这意味着您(还)不能在实际需要内容的最后时刻触发 API 调用。

当您添加流(使用zip.file("filename.txt", myStream))时,JSZip 会暂停它并等待使用它(例如调用zip.generateNodeStream() 或getter)。

所以你可以做的(在当前的 v3.1.2 中),限制内存使用是将所有资源添加为流并调用zip.generateNodeStream({streamFiles:true})。主要缺点是您确实打开了与 Web 服务的连接,并且在流式传输第一个文件时可能会遇到超时(比如说在最后一个文件上)(或者更糟,取决于输入流如何处理 .pause())。

关于streamFiles 和问题的cmets:zip 格式非常适合流式传输。正如the documentation 中所说,streamFiles 选项决定了 zip 文件中文件的 size/crc32 的写入位置:在数据之前(但我们需要将文件临时保存在内存中以计算它们)或在数据之后(流式传输所有内容,将计算值放在最后)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-08-18
    • 2017-08-08
    • 1970-01-01
    • 2012-12-04
    • 2011-04-08
    • 2014-09-14
    • 1970-01-01
    相关资源
    最近更新 更多