在S3中读取并解析CSV文件而不下载整个文件

时间:2016-10-04 20:31:40

标签: node.js amazon-web-services amazon-s3 aws-sdk

使用node.js,目的是将此模块作为AWS Lambda函数运行。

使用s3.getObject()中的aws-sdk,我能够从Amazon S3成功获取一个非常大的CSV文件。目的是读取文件中的每一行,并用每行的主体发出一个事件。

在我发现的所有示例中,看起来S3中的整个CSV文件必须被缓冲或流式传输,转换为字符串然后逐行读取。

s3.getObject(params, function(err, data) {
   var body = data.Body.toString('utf-8');
}

考虑到源CSV文件的大小,此操作需要很长时间。此外,CSV行的长度各不相同,我不确定是否可以使用缓冲区大小作为选项。

问题

有没有办法在node.js中获取S3文件并逐行读取/转换它,这样可以避免首先将整个文件串在内存中?

理想情况下,我更倾向于使用fast-csv和/或node-csv的更好功能,而不是手动循环。

4 个答案:

答案 0 :(得分:13)

您应该只能使用createReadStream method并将其传输到fast-csv:

const s3Stream = s3.getObject(params).createReadStream()
require('fast-csv').fromStream(s3Stream)
  .on('data', (data) => {
    // do something here
  })

答案 1 :(得分:3)

我没有足够的声誉来发表评论,但是到目前为止,'fast-csv'尚不存在可接受的答案方法“ fromStream”。现在,您需要使用parseStream方法:

const s3Stream = s3.getObject(params).createReadStream()
require('fast-csv').parseStream(s3Stream)
  .on('data', (data) => {
    // use rows
  })

答案 2 :(得分:0)

不是逐行排列,但您可以使用Range标头按字节范围获取S3对象。因此,您可以一次读取1000个字节,并在读取数据时管理新行。查看GET Object documentation并搜索Range标题。

答案 3 :(得分:0)

对我来说,解决我的问题的答案是,

  const csv = require('@fast-csv/parse');

  const params = {
    Bucket: srcBucket,
    Key: srcKey,
  };
  const csvFile = s3.getObject(params).createReadStream();

  let parserFcn = new Promise((resolve, reject) => {
    const parser = csv
      .parseStream(csvFile, { headers: true })
      .on("data", function (data) {
        console.log('Data parsed: ', data);
      })
      .on("end", function () {
        resolve("csv parse process finished");
      })
      .on("error", function () {
        reject("csv parse process failed");
      });
  });

  try {
    await parserFcn;
  } catch (error) {
    console.log("Get Error: ", error);
  }