Ich versuche, ein Programm zu schreiben, um eine Zip-Datei von S3 zu erhalten, zu entpacken und dann nach S3 hochzuladen. Aber ich habe zwei Ausnahmen gefunden, die ich nicht fangen kann.
1.StreamContentLengthMismatch: Stream content length mismatch. Received 980323883 of 5770104761 bytes.
Dies geschieht unregelmäßig.
2.NoSuchKey: The specified key does not exist.
Dies passiert, wenn ich den falschen Schlüssel eingebe.
Wenn diese beiden Ausnahmen auftreten, stürzt dieses Programm ab.
Ich möchte diese beiden Ausnahmen richtig einfangen und handhaben.
Ich möchte einen Absturz verhindern.
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
}
Dies ist die Bibliothek, die ich beim Entpacken verwende . https://github.com/mhr3/unzip-stream
Hilf mir!!
Wenn Sie den von NoSuchKey
ausgelösten createReadStream
-Fehler abfangen möchten, haben Sie zwei Möglichkeiten:
Zuerst :
s3.getObjectMetadata(key)
.promise()
.then(() => {
// This will not throw error anymore
s3.getObject().createReadStream();
})
.catch(error => {
if (error.statusCode === 404) {
// Catching NoSuchKey
}
});
Der einzige Fall, in dem Sie keine Fehlermeldung erhalten, wenn die Datei in Sekundenbruchteilen gelöscht wurde, zwischen der Analyse der Antwort von getObjectMetadata
und der Ausführung von createReadStream
.
Zweite :
s3.getObject().createReadStream().on('error', error => {
// Catching NoSuchKey & StreamContentLengthMismatch
});
Dies ist ein generischerer Ansatz und fängt alle anderen Fehler auf, z. B. Netzwerkprobleme.
Sie müssen den ausgegebenen Fehler früher abhören. Ihr Error-Handler sucht nur während des Entpack-Teils nach Fehlern.
Eine vereinfachte Version Ihres Skripts.
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
});
Auf diese Weise müssen Sie AWS nicht noch einmal anrufen, um herauszufinden, ob er existiert.
Sie können Ereignisse (wie Fehler, Daten, Fertigstellung) im Stream abhören, den Sie zurückerhalten. Lesen Sie mehr über Ereignisse
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.
})
Auf Fehler "Kein Schlüssel" getestet.
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()
})
})
Auf Erfolg getestet.
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()
})
})