节点AWS S3 getObject在文件流完成之前触发httpDone

wil*_*ast 2 unzip amazon-s3 node.js aws-sdk

我在节点应用程序中使用AWS s3 getObject方法下载zip文件,然后使用child_process.exec调用unzip:

var file = fs.createWriteStream(file_path);
s3.getObject(params).
on('httpData', function(chunk) { 
    process.stdout.write("."); 
    file.write(chunk); 
}).
on('httpDone', function() { 
    file.end(); 
    console.log('Download Complete'); 
    self.emit('downloadComplete');
}).
send();
Run Code Online (Sandbox Code Playgroud)

并且在downloadComplete事件中,调用此代码,这会引发错误:

exec = require('child_process').exec;
exec('unzip -o -qq ' + src + ' -d ' + dest, function (error, stdout, stderr) { 
    callback(stderr);
});
Run Code Online (Sandbox Code Playgroud)

exec调用返回此错误:

End-of-central-directory signature not found.  Either this file is not
a zipfile, or it constitutes one disk of a multi-part archive.  In the
latter case the central directory and zipfile comment will be found on
the last disk(s) of this archive.
Run Code Online (Sandbox Code Playgroud)

但是,如果我在尝试解压缩之前设置了一个短暂的超时,即:

setTimeout(function() {
    self.emit('downloadComplete');
}, 100);
Run Code Online (Sandbox Code Playgroud)

有用.AWS节点库中是否存在错误,或者我使用错误的完成事件?

msc*_*dex 6

您应该finish在文件流的事件处理程序中发出下载完成事件:

var file = fs.createWriteStream(file_path);
file.on('finish', function() {
  self.emit('downloadComplete');
});
s3.getObject(params).
  on('httpData', function(chunk) { 
    process.stdout.write("."); 
    file.write(chunk); 
  }).
  on('httpDone', function() { 
    file.end(); 
    console.log('Download Complete'); 
  }).
  send();
Run Code Online (Sandbox Code Playgroud)

在一个不相关的说明中,您可能还应该使用普通流,以便当磁盘无法跟上时,背压可以发挥作用.例如:

var file = fs.createWriteStream(file_path);
s3.getObject(params)
  .createReadStream()
  .pipe(file)
  .on('finish', function() {
    self.emit('downloadComplete');
  });
Run Code Online (Sandbox Code Playgroud)