私はs3からZipファイルを取得し、それを解凍し、それをS3にアップロードするプログラムを作成しようとしています。しかし、私はキャッチできない2つの例外を見つけました。
1。StreamContentLengthMismatch: Stream content length mismatch. Received 980323883 of 5770104761 bytes.
これは不規則に発生します。
2。NoSuchKey: The specified key does not exist.
これは、間違ったキーを入力したときに発生します。
これらの2つの例外が発生すると、このプログラムはクラッシュします。
これらの2つの例外を正しくキャッチして処理したいと思います。
クラッシュを防ぎたい。
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
助けて!!
NoSuchKey
によってスローされるcreateReadStream
エラーをキャッチしたい場合、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
の実行の間で、ファイルが一瞬で削除された場合にエラーをキャッチしない唯一のケース
2番目:
s3.getObject().createReadStream().on('error', error => {
// Catching NoSuchKey & StreamContentLengthMismatch
});
これはより一般的なアプローチであり、ネットワークの問題など、他のすべてのエラーをキャッチします。
発生したエラーを早期にリッスンする必要があります。エラーハンドラは、解凍部分のエラーのみを探します。
スクリプトの簡易バージョン。
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が存在するかどうかを確認するためにAWSに追加の呼び出しを行う必要はありません。
受信しているストリーム内のイベント(エラー、データ、終了など)をリッスンできます。 イベントの詳細を読む
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()
})
})