节点,缓冲区,流,保存到文件

时间:2016-09-11 14:09:56

标签: node.js

我正在尝试获取一个文件(从S3返回为Buffer),解压缩它(这是一个流),然后将其保存到/tmp/foo的磁盘。

如果我以异步方式处理untar(zlib.gunzip())函数,如果此脚本一次只能处理一个文件,它是否重要?使用流可以获得什么?

var getS3Args = { bucket: 'foo', key: 'bar.tar.gz' }

lib.getS3Object(getS3Args, function(getS3ObjectResponse) {
  zlib.gunzip(getS3ObjectResponse.Body, function(err, result) {
    if(err) return console.error(err);

    // ?

    console.log(result);
    return callback(result);
  });
});

1 个答案:

答案 0 :(得分:3)

您可以直接从aws-sdk获取S3中的数据流。使用流时获得的优势是它使用的内存要少得多,因为它不需要在内存中使用整个缓冲区来对其进行操作。 Streams一次在小块上运行,然后这些块在处理完之后会被垃圾收集。使用您当前的方法,如果您想从S3下载1TB blob,您可能会遇到内存不足错误,因为您无法将整个缓冲区放入内存中。使用流时,您可能永远不会看到多于几MB的内存被使用,因为一个块将从HTTP响应中下来,然后该块将被解压缩,解压缩并自行写入您的文件系统而无需等待对于整个HTTP响应。

var AWS = require('aws-sdk')
var S3 = new AWS.S3()
var fs = require('fs')
var tar = require('tar')
var zlib = require('zlib')
var path = require('path')
var mkdirp = require('mkdirp')
var getS3Args = { bucket: 'foo', key: 'bar.tar.gz' }
var dest = '/path/to/destination'

S3.getObject(getS3Args)
  .createReadStream()
  .pipe(zlib.Unzip())
  .pipe(tar.Parse())
  .on('entry', function(entry) {
    var isDir     = 'Directory' === entry.type
    var fullpath  = path.join(dest, entry.path)
    var directory = isDir ? fullpath : path.dirname(fullpath)
    mkdirp(directory, function(err) {
      if (err) throw err
      if (!isDir) entry.pipe(fs.createWriteStream(fullpath))
    })
  })