J'essaye d'écrire un programme pour obtenir un fichier Zip de s3, le décompresser, puis le télécharger sur S3 . Mais j'ai trouvé deux exceptions que je ne peux pas attraper.
1.StreamContentLengthMismatch: Stream content length mismatch. Received 980323883 of 5770104761 bytes.
Cela se produit de manière irrégulière.
2.NoSuchKey: The specified key does not exist.
Cela se produit lorsque je saisis la mauvaise clé.
Lorsque ces deux exceptions se produisent, ce programme se bloque.
Je voudrais attraper et gérer ces deux exceptions correctement.
Je veux éviter un crash.
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
}
C’est la bibliothèque que j’utilise pour décompresser . https://github.com/mhr3/unzip-stream
Aidez moi!!
Si vous souhaitez intercepter l'erreur NoSuchKey
renvoyée par createReadStream
, vous avez 2 options:
Premier :
s3.getObjectMetadata(key)
.promise()
.then(() => {
// This will not throw error anymore
s3.getObject().createReadStream();
})
.catch(error => {
if (error.statusCode === 404) {
// Catching NoSuchKey
}
});
Le seul cas où vous ne rencontrerez pas d'erreur si le fichier était supprimé en une fraction de seconde, entre l'analyse de la réponse de getObjectMetadata
et l'exécution de createReadStream
Seconde :
s3.getObject().createReadStream().on('error', error => {
// Catching NoSuchKey & StreamContentLengthMismatch
});
Cette approche est plus générique et interceptera toutes les autres erreurs, telles que les problèmes de réseau.
Vous devez écouter l'erreur émise plus tôt. Votre gestionnaire d'erreurs recherche uniquement les erreurs pendant la décompression.
Une version simplifiée de votre script.
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
});
De cette manière, vous n'avez pas besoin d'appeler AWS pour savoir s'il existe ou non.
Vous pouvez écouter les événements (tels que erreur, données, fin) du flux que vous recevez. En savoir plus sur les événements
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.
})
Testé pour l'erreur "No Key".
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()
})
})
Testé pour le succès.
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()
})
})