Lambda函数s3.getObject返回“内部服务器错误”

时间:2018-09-24 21:23:42

标签: amazon-web-services amazon-s3 aws-lambda aws-sdk-nodejs

此代码在使用nodejs的情况下在本地运行良好。图像从s3下载,并写入文件。

但是,在Lambda中(使用nodejs 8.10),在日志中对此进行测试时,出现“内部服务器错误”消息:

“由于配置错误,执行失败:Lambda代理响应格式错误”

我在回调中使用了lambda代理响应,但是显然没有发现S3的某些AWS开发工具包错误。

我确实具有Lambda可以访问的具有S3完全访问权限的角色设置。

我的第一个Lambda函数缺少什么?我已正确遵循的文档和教程,无法正常工作。

const async = require('async')
const aws = require('aws-sdk')
const fs = require('fs')
const exec = require('child_process').exec

const bucket = 'mybucket'
const s3Src = 'bucket_prefix'
const s3Dst = 'new_prefix'
const local = `${__dirname}/local/`
aws.config.region = 'us-west-2'
const s3 = new aws.S3()

exports.handler = async (event, context, callback) => {
    const outputImage = 'hello_world.png'
    const rack = JSON.parse(event.body)
    const images = my.images

    async.waterfall([
            function download(next) {
                let downloaded = 0
                let errors = false
                let errorMessages = []

                for (let i = 0; i < images.length; i++) {
                    let key = `${s3Src}/${images[i].prefix}/${images[i].image}`,
                        localImage = `${local}${images[i].image}`

                    getBucketObject(bucket, key, localImage).then(() => {
                        ++downloaded
                    if (downloaded === images.length) { // js is non blocking, need to check if all images have been downloaded. If so, then go to next function
                        if (errors) {
                            next(errorMessages.join(' '))
                        } else {
                            next(null)
                        }
                    }
                }).catch(error => {
                    errorMessages.push(`${error} - ${localImage}`)
                    ++downloaded
                    errors = true
                })
            }

            function getBucketObject(bucket, key, dest) {
                return new Promise((resolve, reject) => {
                    let ws = fs.createWriteStream(dest)

                    ws.once('error', (err) => {
                        return reject(err)
                    })

                    ws.once('finish', () => {
                        return resolve(dest)
                    })

                    let s3Stream = s3.getObject({
                        Bucket: bucket,
                        Key: key
                    }).createReadStream()

                    s3Stream.pause() // Under load this will prevent first few bytes from being lost

                    s3Stream.on('error', (err) => {
                        return reject(err)
                    })

                    s3Stream.pipe(ws)
                    s3Stream.resume()
                })
            }
        }
    ], err => {
        if (err) {
            let response = {
                "statusCode": 400,
                "headers": {
                    "my_header": "my_value"
                },
                "body": JSON.stringify(err),
                "isBase64Encoded": false
            }
            callback(null, response)
        } else {
            let response = {
                "statusCode": 200,
                "headers": {
                    "my_header": "my_value"
                },
                "body": JSON.stringify(`<img src="${local}${outputImage}" />`),
                "isBase64Encoded": false
            }
            callback(null, response)
        }
    }
)

}

2 个答案:

答案 0 :(得分:1)

应始终将响应发送给回调函数。您的代码仅在错误时发送响应。这就是Lambda执行器认为您的代码失败的原因。

顺便说一句-您应该将async.waterfall中的功能用逗号分隔为两个任务吗?

答案 1 :(得分:0)

在本地,我一直在运行nodejs 10.10,而lambda当前为8.10。我敢肯定那是很大的一部分。最后,我不得不删除异步。我不得不将getBucketObject函数移出瀑布。一旦进行了这些调整,它便开始工作。另一个问题是下载的图像需要进入“ / tmp”目录。

[2018-09-25 09:47:35]  [0.18ms]  INSERT INTO "profiles" ("created_at","updated_at","deleted_at","email","last_login") VALUES ('2018-09-25 09:47:35','2018-09-25 09:47:35',NULL,'user@domain.com','2018-09-25 09:47:35')
[1 rows affected or returned ]