使用 Node.js 流将 zip 数据从内存增量上传到 AWS S3 存储桶上的单个文件

问题描述 投票:0回答:1

我有一个 ReadableStream 未压缩的文本数据,我需要将其存储在 S3 上的单个 zip 压缩文件中。

我不想做的事:

  • 将所有数据加载到内存中。
  • 将数据写入本地磁盘。

我想做的事:

  • 从输入流中增量读取数据,对其进行zip压缩并直接上传到S3(逐块)。结果应该是一个 zip 文件。

到目前为止我尝试过的:

import {S3} from 'aws-sdk';
import {PassThrough} from 'stream';
import archiver from 'archiver';

const s3 = new S3({region: 'us-east-1'});

(async () => {
    const stream = new PassThrough();
    const archive = archiver('zip', {
        zlib: { level: 9 }
    });
    archive.pipe(stream);

    const upload = s3.upload({
        Bucket: 'my-bucket',
        Key: 'stream.zip',
        Body: stream,
    }).promise();

    // Assume this is the readable stream we are reading from
    for (let i = 0; i < 100; i++) {
        const textData = `text-data-${i}`;
        archive.append(Buffer.from(`${textData}\n`, 'utf8'), { name: `file-${i}.txt` });
    }

    await archive.finalize();
    await upload;
})();

这是不正确的,因为它在 S3 上的输出存档

stream.zip
中生成多个文件(
file-1.txt
file-2.txt
等)。另一方面,如果我在将数据附加到
archive
时使用单个文件名,则需要在附加之前将所有数据缓冲到内存中,这会抵消增量流数据的目的。

有谁知道这个问题的解决办法吗?

node.js amazon-web-services amazon-s3 stream
1个回答
0
投票

我可能找到了一个解决方案,基本上是将 Stream 而不是 Buffer 附加到存档器:

import {S3} from 'aws-sdk';
import {PassThrough} from 'stream';
import archiver from 'archiver';

const s3 = new S3({region: 'us-east-1'});

(async () => {
    const inputStream = new PassThrough();
    const outputStream = new PassThrough();

    const archive = archiver('zip', {
        zlib: { level: 9 }
    });
    archive.pipe(outputStream);
    // Append a stream instead of a Buffer. This should result in a single zipped file.
    archive.append(inputStream, {name: 'myfile.txt'});

    const upload = s3.upload({
        Bucket: 'my-bucket',
        Key: 'stream.zip',
        Body: outputStream,
    }).promise();
    
    for (let i = 0; i < 100; i++) {
        const textData = `text-data-${i}\n`;
        inputStream.write(textData, 'utf-8');
    }

    inputStream.end();
    await Promise.all([
        archive.finalize(),
        upload,    
    ]);
    outputStream.end();    
})();

很高兴听到对此的意见。

© www.soinside.com 2019 - 2024. All rights reserved.