it-swarm.com.ru

s3.getObject (). createReadStream (): как отловить ошибку?

Я пытаюсь написать программу для получения Zip-файла из s3, разархивировать его, а затем загрузить в S3 . Но я обнаружил два исключения, которые не могу поймать.

1.StreamContentLengthMismatch: Stream content length mismatch. Received 980323883 of 5770104761 bytes. Это происходит нерегулярно.

2.NoSuchKey: The specified key does not exist. Это происходит, когда я ввожу неправильный ключ.

Когда происходят эти два исключения, эта программа падает.

Я хотел бы поймать и обработать эти два исключения правильно.

Я хочу предотвратить аварию.

   const unzipUpload = () => {
        return new Promise((resolve, reject) => {
            let rStream = s3.getObject({Bucket: 'bucket', Key: 'hoge/hoge.Zip'})
                .createReadStream()
                    .pipe(unzip.Parse())
                    .on('entry', function (entry) {
                        if(entry.path.match(/__MACOSX/) == null){

                            // pause
                            if(currentFileCount - uploadedFileCount > 10) rStream.pause()

                            currentFileCount += 1
                            var fileName = entry.path;
                            let up = entry.pipe(uploadFromStream(s3,fileName))

                            up.on('uploaded', e => {
                                uploadedFileCount += 1
                                console.log(currentFileCount, uploadedFileCount)

                                //resume
                                if(currentFileCount - uploadedFileCount <= 10) rStream.resume()

                                if(uploadedFileCount === allFileCount) resolve()
                                entry.autodrain()
                            }).on('error', e => {
                                reject()
                            })
                        }

                    }).on('error', e => {
                        console.log("unzip error")
                        reject()
                    }).on('finish', e => {
                        allFileCount = currentFileCount
                    })
            rStream.on('error', e=> {
                console.log(e)
                reject(e)
            })
        })
    }

    function uploadFromStream(s3,fileName) {
        var pass = new stream.PassThrough();

        var params = {Bucket: "bucket", Key: "hoge/unzip/" + fileName, Body: pass};
        let request = s3.upload(params, function(err, data) {
            if(err) pass.emit('error')
            if(!err) pass.emit('uploaded')
        })
        request.on('httpUploadProgress', progress => {
            console.log(progress)
        })

        return pass
    }

Это библиотека, которую я использую при распаковке . https://github.com/mhr3/unzip-stream

Помоги мне!!

15
tomoya ishizaka

Если вы хотите отловить ошибку NoSuchKey, выданную createReadStream, у вас есть 2 варианта:

  1. Проверьте, существует ли ключ, прежде чем читать его.
  2. Ошибка отлова из потока

Первый :

s3.getObjectMetadata(key)
  .promise()
  .then(() => {
    // This will not throw error anymore
    s3.getObject().createReadStream();
  })
  .catch(error => {
    if (error.statusCode === 404) {
      // Catching NoSuchKey
    }
  });

Единственный случай, когда вы не поймаете ошибку, если файл был удален за доли секунды, между анализом ответа от getObjectMetadata и запуском createReadStream

Второй

s3.getObject().createReadStream().on('error', error => {
    // Catching NoSuchKey & StreamContentLengthMismatch
});

Это более общий подход, который будет перехватывать все другие ошибки, например проблемы сети.

13
Vlad Holubiev

Вы должны прослушать выданную ошибку ранее. Ваш обработчик ошибок ищет только ошибки во время распаковки.

Упрощенная версия вашего скрипта.

s3.getObject(params)
.createReadStream()
.on('error', (e) => {
  // handle aws s3 error from createReadStream
})
.pipe(unzip)
.on('data', (data) => {
  // retrieve data
})
.on('end', () => {
  // stream has ended
})
.on('error', (e) => {
  // handle error from unzip
});

Таким образом, вам не нужно совершать дополнительный звонок в AWS, чтобы выяснить, существует ли он.

2
dmo

Вы можете прослушивать события (такие как ошибка, данные, завершение) в потоке, который вы получаете обратно. Подробнее о событиях

function getObjectStream (filePath) {
  return s3.getObject({
    Bucket: bucket,
    Key: filePath
  }).createReadStream()
}

let readStream = getObjectStream('/path/to/file.Zip')
readStream.on('error', function (error) {
  // Handle your error here.
})

Проверено на отсутствие ошибки.

it('should not be able to get stream of unavailable object', function (done) {
  let filePath = 'file_not_available.Zip'

  let readStream = s3.getObjectStream(filePath)
  readStream.on('error', function (error) {
    expect(error instanceof Error).to.equal(true)
    expect(error.message).to.equal('The specified key does not exist.')
    done()
  })
})

Проверено на успех.

it('should be able to get stream of available object', function (done) {
  let filePath = 'test.Zip'
  let receivedBytes = 0

  let readStream = s3.getObjectStream(filePath)
  readStream.on('error', function (error) {
    expect(error).to.equal(undefined)
  })
  readStream.on('data', function (data) {
    receivedBytes += data.length
  })
  readStream.on('finish', function () {
    expect(receivedBytes).to.equal(3774)
    done()
  })
})
1
Rash