使用存档器创建内存中的.zip,然后在节点服务器上使用koa将此文件发送到客户端

时间:2018-12-04 22:23:14

标签: javascript node.js zip koa archiverjs

我(作为具有Koa框架的节点服务器),需要使用JSON blob,将其转换为扩展名为.json的文件,然后将其粘贴在zip存档中,然后将存档作为文件附件发送以响应来自客户的请求。

执行此操作的方法似乎是使用Archiver工具。据我所知,这样做的方法是创建一个存档,将json博客附加为.json文件(它会自动在存档中创建该文件吗?),然后将.zip“管道传输”到响应对象。我理解失败的地方是“管道”范例,这主要是由于没有理解这些文档所说的话。

Archiver docs以及某些stackoverflow answers,使用的语言对我来说意味着“通过将(zip文件)管道传输到HTTP响应对象,将数据流式传输到客户端。{{3 }}说说ctx.body可以直接设置为流,所以这是我尝试的方法:

尝试1

    const archive = archiver.create('zip', {});
    ctx.append('Content-Type', 'application/zip');
    ctx.append('Content-Disposition', `attachment; filename=libraries.zip`);
    ctx.response.body = archive.pipe(ctx.body);
    archive.append(JSON.stringify(blob), { name: 'libraries.json'});
    archive.finalize();

逻辑:应将响应主体设置为流,并且该流应为存档器流(指向ctx.body)。

结果:.zip文件在客户端下载,但是zip格式不正确(无法打开)。

尝试2

    const archive = archiver.create('zip', {});
    ctx.append('Content-Type', 'application/zip');
    ctx.append('Content-Disposition', `attachment; filename=libraries.zip`);
    archive.pipe(ctx.body);
    archive.append(JSON.stringify(blob), { name: 'libraries.json'});
    archive.finalize();

逻辑:在“指向流指向它”之后,将主体设置为流似乎很愚蠢,因此请复制其他stackoverflow示例。

结果:与尝试1相同。

尝试3

基于Koa docs

    const archive = archiver.create('zip', {});
    ctx.append('Content-Type', 'application/zip');
    ctx.append('Content-Disposition', `attachment; filename=libraries.zip`);
    ctx.body = ctx.request.pipe(archive);
    archive.append(JSON.stringify(body), { name: 'libraries.json'});
    archive.finalize();

结果:ctx.request.pipe不是函数。

我可能没有读正确的书,但是所有在线内容似乎都表明archive.pipe(some sort of client-sent stream)“神奇地行得通”。 https://github.com/koajs/koa/issues/944,“流魔术”是他们使用的词。

我如何在内存中将JSON blob转换为.json,然后将该.json附加到.zip文件中,然后将其发送到客户端并下载,然后可以成功解压缩以查看该文件。 json

编辑:如果我在ctx.body之后使用console.log archive.finalize(),它会显示一个ReadableStream,这似乎是正确的。但是,它的“路径”属性令我感到担忧-它是我想知道的index.html-在客户端的“响应预览”中,我看到了index.html的字符串化版本。该文件仍在下载.zip,因此我不太担心,但是现在我想知道是否与此有关。

EDIT2:更深入地了解客户端的响应,看来发送回的数据正好是我们的index.html,所以现在我很困惑。

1 个答案:

答案 0 :(得分:0)


const passThrough = new PassThrough();
const archive = archiver.create('zip', {});

archive.pipe(passThrough);
archive.append(JSON.stringify(blob), { name: 'libraries.json'});
archive.finalize();

ctx.body = passThrough;
ctx.type = 'zip';

这应该适用于您的用例,因为存档器实际上不是我们应该传递给 ctx.body 的流,我猜。