让我提前为这个糟糕的代码道歉。我的 Node 经验几乎为零,并且在后端使用 React 应用程序和 Elixir 编写所有 JS。我正在努力在 NodeJS 中编写一个正确的 Lambda 函数,并且基本上已经从 Google/SO/试验和错误等中拼凑了一些东西。
我正在做的事情如下:
- 用户想要上传文件,以便向后端发送一些信息。
- 后端生成预签名 key 。
- 前端将文件发送到 S3。
- S3 触发事件并执行 Lambda
- Lambda 现在会检查 mimetype,如果文件错误,则会从 S3 存储桶中删除该文件,并向我的后端发出 DELETE API 调用,告诉它删除上传照片所属的行。
我遇到的困难是,当我在 s3.deleteObject 调用中对后端进行 API 调用时,我得到的结果非常不一致。很多时候,它会在同一个 Lambda 执行中连续发送两个删除请求。有时,它甚至从未调用后端,只是运行并显示完整内容,而没有真正将任何内容记录到 Cloudwatch。
我的代码如下:
const aws = require('aws-sdk');
const s3 = new aws.S3({apiVersion: '2006-03-01'});
const fileType = require('file-type');
const imageTypes = ['image/gif', 'image/jpeg', 'image/png'];
const request = require('request-promise');
exports.handler = async (event, context) => {
// Get the object from the event and show its content type
const bucket = event.Records[0].s3.bucket.name;
const key = decodeURIComponent(
event.Records[0].s3.object.key.replace(/\+/g, ' ')
);
const params = {
Bucket: bucket,
Key: key,
};
try {
const {Body} = await s3.getObject(params).promise();
const fileBuffer = new Buffer(Body, 'base64');
const fileTypeInfo = fileType(fileBuffer);
if (
typeof fileTypeInfo !== 'undefined' &&
fileTypeInfo &&
imageTypes.includes(fileTypeInfo.mime)
) {
console.log('FILE IS OKAY.');
} else {
await s3
.deleteObject(params, function(err, data) {
console.log('FILE IS NOT AN IMAGE.');
if (err) {
console.log('FAILED TO DELETE.');
} else {
console.log('DELETED ON S3. ATTEMPTING TO DELETE ON SERVER.');
const url =
`http://MYSERVERHERE:4000/api/event/${params.Key.split('.')[0]}`;
const options = {
method: 'DELETE',
uri: url,
};
request(options)
.then(function(response) {
console.log('RESPONSE: ', response);
})
.catch(function(err) {
console.log('ERROR: ', err);
});
}
})
.promise();
}
return Body;
} catch (err) {
const message = `Error getting object ${key} from bucket ${bucket}. Make sure they exist and your bucket is in the same region as this function.`;
console.log(message);
throw new Error(message);
}
};
这几天来一直让我发疯。感谢任何帮助来解释为什么我会从这样的 Lambda 函数中得到意外的结果。
最佳答案
更新您的else部分后请检查是否正确使用await
Please try below code.
exports.handler = async (event, context) => {
// Get the object from the event and show its content type
const bucket = event.Records[0].s3.bucket.name;
const key = decodeURIComponent(
event.Records[0].s3.object.key.replace(/\+/g, ' ')
);
const params = {
Bucket: bucket,
Key: key,
};
try {
const {Body} = await s3.getObject(params).promise();
const fileBuffer = new Buffer(Body, 'base64');
const fileTypeInfo = fileType(fileBuffer);
if (
typeof fileTypeInfo !== 'undefined' &&
fileTypeInfo &&
imageTypes.includes(fileTypeInfo.mime)
) {
console.log('FILE IS OKAY.');
} else {
await s3.deleteObject(params).promise(); //fail then catch block execute
console.log('DELETED ON S3. ATTEMPTING TO DELETE ON SERVER.');
const url =
`http://MYSERVERHERE:4000/api/event/${params.Key.split('.')[0]}`;
const options = {
method: 'DELETE',
uri: url,
};
let response = await request(options); ////fail then catch block execute
console.log(response);
}
return Body;
} catch (err) {
console.log(err);
const message = `Error getting object ${key} from bucket ${bucket}. Make sure they exist and your bucket is in the same region as this function.`;
console.log(message);
throw new Error(message);
}
};
关于node.js - 从 AWS Lambda 进行 API 调用结果不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52982051/