无法使用nodeJS从S3下载文件:几个文件都没有完成

时间:2017-03-07 18:23:06

标签: node.js amazon-s3

这让我疯了。

我需要服务器从S3下载100个相对较小的文件(最多2 Mb)。

它总是适用于约95%的文件,但它会阻止最后的6-8个文件。永远不会调用resolvereject回调...

我尝试并行下载文件......

  • 有人经历过这个吗?
  • 可能是数据包丢失且流不关闭吗?
  • 是否有最大并发下载次数?

这里是代码,在95%的情况下技术上有效:

  let singleGetFromS3 = (bucket, fileName) => {
    return new Promise((resolve, reject) => {
      let extension = getFileNameExtension(fileName);
      fs.stat(`./${fileName}`, (err, stat) => {
        if (err === null) {
          console.log(`${fileName} exists locally`);
          resolve(fileName);
        } else if(err.code === 'ENOENT') {
          let params = {Bucket: bucket, Key: fileName};
          let file = require('fs').createWriteStream(`./tmp-${fileName}`);
          s3.getObject(params).createReadStream()
            .on('error', (error) => { return reject(error); })
            .on('end', () => {
              fs.rename(`./tmp-${fileName}`, `./${fileName}`, reject);
              return resolve(fileName);
            })
            .pipe(file);
        } else {
          reject(err);
        }
      });
    });
  };

使用:

"aws-sdk": "^2.23.0",
node --version
v4.5.0

1 个答案:

答案 0 :(得分:2)

看起来您正在侦听错误的事件以何时解决。您不希望在从S3的Readable读取所有字节时解决,您希望在file完成写入时解决。

let singleGetFromS3 = (bucket, fileName) => {
    return new Promise((resolve, reject) => {
      let extension = getFileNameExtension(fileName);
      fs.stat(`./${fileName}`, (err, stat) => {
        if (err === null) {
          console.log(`${fileName} exists locally`);
          resolve(fileName);
        } else if(err.code === 'ENOENT') {
          let params = {Bucket: bucket, Key: fileName};
          let file = require('fs').createWriteStream(`./tmp-${fileName}`);    

          // Listen for the file to be done writing, then resolve
          file.on('finish', () => {
              fs.rename(`./tmp-${fileName}`, `./${fileName}`, reject);
              return resolve(fileName);
            })

          s3.getObject(params).createReadStream()
            .on('error', (error) => { return reject(error); })
            .pipe(file);
        } else {
          reject(err);
        }
      });
    });
  };