目标:用户上传到 S3,触发 Lambda 获取文件并发送到 Google Vision API 进行分析,返回结果。
据此,需要本google-cloud
机库,并且必须针对 lambda 正在运行的操作系统进行编译。使用lambda-packager
引发了错误,但使用带有 Node 和 NPM 的 EC2 来运行安装时出现了一些 Internet 搜索。本着破解这一点的精神,这就是我所做的以使其大部分工作*。至少 lambda 停止给我 ELF 标头错误。
我目前的问题是有两种调用 Vision API 的方法,它们都不起作用并且都返回不同的错误(大部分)。
公共代码:此代码始终相同,位于函数的顶部,我将其分开以使后面的代码块专注于该问题。
'use strict';
const AWS = require('aws-sdk');
const S3 = new AWS.S3();
const Bucket = 'my-awesome-bucket';
const gCloudConfig = {
projectId: 'myCoolApp',
credentials: {
client_email: 'your.serviceapi@project.email.com',
private_key: 'yourServiceApiPrivateKey'
}
}
const gCloud = require('google-cloud')(gCloudConfig);
const gVision = gCloud.vision();
使用detect()
:此代码总是返回错误Error: error:0906D06C:PEM routines:PEM_read_bio:no start line
。理论上它应该可以工作,因为 URL 是公开的。通过搜索错误,我认为它可能是 HTTPS 问题,所以我什至尝试了一种变体,将 HTTPS 替换为 HTTP,但得到了相同的错误。
exports.handler = (event, context, callback) => {
const params = {
Bucket,
Key: event.Records[0].s3.object.key
}
const img = S3.getSignedUrl('getObject', params);
gVision.detect(img, ['labels','text'], function(err, image){
if(err){
console.log('vision error', err);
}
console.log('vision result:', JSON.stringify(image, true, 2));
});
}
使用detectLabels()
:此代码始终返回Error: ENAMETOOLONG: name too long, open ....[the image in base64]...
。在一个建议中,人们认为该方法不应传递 base64 图像,而应传递公共路径;这可以解释为什么它说名称太长(base64 图像就是 URL)。不幸的是,这从上面给出了 PEM 错误。我也尝试过不进行 base64 编码并直接从 aws 传递对象缓冲区,但这也导致了 PEM 错误。
exports.handler = (event, context, callback) => {
const params = {
Bucket,
Key: event.Records[0].s3.object.key
}
S3.getObject(params, function(err, data){
const img = data.Body.toString('base64');
gVision.detectLabels(img, function(err, labels){
if(err){
console.log('vision error', err);
}
console.log('vision result:', labels);
});
});
}
根据Best Practices,图像应该是 base64 编码的。
从 API 文档和示例以及其他任何内容来看,我似乎正确地使用了这些。我觉得我已经阅读了所有这些文档一百万次。
如果 NAMETOOLONG 错误期待 base64 的东西,我不确定该怎么做。这些图像不超过 1MB。
* PEM 错误似乎与凭证有关,并且因为我了解所有这些凭证如何工作以及如何在 EC2(没有任何类型的 PEM 文件)上编译模块,这可能是我的问题。也许我需要在运行之前设置一些凭据npm install
,就像需要安装在 linux 机器上一样?这开始超出我的理解范围,所以我希望这里有人知道。
理想情况下,使用detect
会更好,因为我可以指定我想要检测的内容,但只要从 Google 获得任何有效的响应就会很棒。你们都可以提供的任何线索将不胜感激。