1

我正在研究使用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吗?

4

1 回答 1

0

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

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

当你添加一个流(带有zip.file("filename.txt", myStream))时,JSZip 将暂停它并等待使用它的东西(例如调用zip.generateNodeStream()或 getter)。

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

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

于 2016-08-29T22:58:48.020 回答