Как получить объекты S3 в цикле? - PullRequest
0 голосов
/ 22 мая 2018

В Node.js я пытаюсь получить объекты, просматривая массив, используя методы fs.createReadStream и fs.createWriteStream.

В документации AWS показано, как получить один объект с помощью s3.getObject(params).createReadStream().pipe(file);

Но с параметрами и s3, установленными как

  const params = { Bucket:'user_events' };
  const s3 = new AWS.S3();

Когда я вызываю свою функцию:

  function gets3Objects(eventsArray) {
    console.log('--> finding files from s3...');
    const arrLen = eventsArray.length;
    let iter = 0;

    s3.listObjects(params, (err, data) => {
      for (let i = 0; i < arrLen; i += 1) {
        let  file = eventsArray[i];
        params.Key = file;
        let fileOut = fs.createWriteStream(`./tmp/${file}`);
        let stream = s3.getObject(params).createReadStream().pipe(fileOut);
        console.log(i, arrLen, eventsArray[i]);

        stream.on('close', () => {
          iter += 1;
          console.log(`${i} -- file added: ${eventsArray[i]}`);

          if (iter === arrLen) {
            console.log('-- success! --');
            delete params.Key;
            return;
          }
        });
    });
  }

Выход выдаёт:

--> finding files from s3...
0 9 'harry_test_audio_09.wav'
1 9 'harry_test_audio_08.wav'
2 9 'harry_test_audio_07.wav'
3 9 'harry_test_audio_06.wav'
4 9 'harry_test_audio_05.wav'
5 9 'harry_test_audio_04.wav'
6 9 'harry_test_audio_03.wav'
7 9 'harry_test_audio_02.wav'
8 9 'harry_test_audio_01.wav'
6 -- file added: harry_test_audio_03.wav
8 -- file added: harry_test_audio_01.wav
7 -- file added: harry_test_audio_02.wav
0 -- file added: harry_test_audio_09.wav
5 -- file added: harry_test_audio_04.wav
1 -- file added: harry_test_audio_08.wav
3 -- file added: harry_test_audio_06.wav
4 -- file added: harry_test_audio_05.wav
2 -- file added: harry_test_audio_07.wav
-- success! --

Какойвыдает 9 файлов с правильными именами, в каждом из которых содержится только содержимое первого файла.

Я также пытался использовать stream.on('finish' ... и stream.on('end' ... с похожими результатами.

Что я делаю не так?

1 Ответ

0 голосов
/ 16 ноября 2018

Я столкнулся с той же проблемой, и это было связано с плохим замыканием в цикле.Решение состоит в том, чтобы создать копию параметров, которые не будут использоваться всеми итерациями.

function gets3Objects(eventsArray) {
  console.log('--> finding files from s3...');
  const arrLen = eventsArray.length;
  let iter = 0;

  s3.listObjects(params, (err, data) => {
    for (let i = 0; i < arrLen; i += 1) {
      let  fileParams = {
        Bucket: 'user_events',
        Key: eventsArray[i]
      }
      let fileOut = fs.createWriteStream(`./tmp/${file}`);
      let stream = s3.getObject(fileParams).createReadStream().pipe(fileOut);
      console.log(i, arrLen, eventsArray[i]);

      stream.on('close', () => {
        iter += 1;
        console.log(`${i} -- file added: ${eventsArray[i]}`);

        if (iter === arrLen) {
          console.log('-- success! --');
          return;
        }
      });
    }
  });
}
...