s3.getObject().createReadStream():如何捕获错误?

tom*_*aka 21 javascript stream amazon-s3 amazon-web-services node.js

我正在尝试编写程序从s3获取zip文件,解压缩,然后将其上传到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
    }
Run Code Online (Sandbox Code Playgroud)

这是解压缩时使用的库. https://github.com/mhr3/unzip-stream

帮我!!

Vla*_*iev 16

如果您想捕获NoSuchKeycreateReadStream您抛出的错误,有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
    }
  });
Run Code Online (Sandbox Code Playgroud)

唯一的情况是,如果文件在瞬间被删除,在解析响应getObjectMetadata和运行之间,您将不会捕获错误createReadStream

第二:

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

这是一种更通用的方法,可以捕获所有其他错误,例如网络问题.

  • 您的第二个解决方案不起作用,它不会捕获 NoSuchKey 错误。我还没有找到捕获此错误的方法,因此解决方案 1 似乎是这里唯一的方法。 (4认同)
  • 谢谢 !!你的第一个想法对我来说是一个创新的想法。对于第二个想法,有些东西不起作用。 (2认同)
  • 我不相信 getObjectMetadata() 是 Node.js S3 SDK 上的有效方法 --- 我认为您正在寻找的是 `s3.headObject({ Bucket: &lt;bucket&gt;, Key: &lt;key&gt; } ):` https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#headObject-property (2认同)

dmo*_*dmo 12

您需要更早地侦听发出的错误。您的错误处理程序仅在解压缩部分查找错误。

脚本的简化版本。

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
});
Run Code Online (Sandbox Code Playgroud)

这样,您无需额外调用 AWS 来确定它是否存在。

  • 这“应该”有效,但由于某种原因却不起作用。来自“node_modules/aws-sdk/lib/request.js:31”的错误始终会转义事件侦听器并终止进程。 (2认同)