【问题标题】:AWS Lambda w/ Google Vision API throwing PEM_read_bio:no start line or Errno::ENAMETOOLONGAWS Lambda w/Google Vision API 抛出 PEM_read_bio:no start line 或 Errno::ENAMETOOLONG
【发布时间】:2016-10-13 23:42:39
【问题描述】:

目标:用户上传到 S3,触发 Lambda 获取文件并发送到 Google Vision API 进行分析,返回结果。

根据this,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 获得任何有效响应就很棒了。大家能提供的任何线索都将不胜感激。

【问题讨论】:

  • 此外,在有人建议在整个 Shebang 中使用更多的 Google Cloud 之前,目前这不是一个选择。如果 AWS 有我不知道的类似于 Vision API 的东西,请告诉我。

标签: javascript amazon-ec2 lambda google-cloud-vision


【解决方案1】:

因此,与另一位同事的对话让我考虑放弃 API 的整个加载并使用 google-cloud 模块。相反,我应该考虑通过 curl 尝试 Cloud REST API,看看它是否可以这样工作。

长话短说,发出 HTTP 请求并使用 Google Cloud 的 REST API 是我解决此问题的方法。

这是我现在拥有的工作 lambda 函数。可能仍需要调整,但这是可行的。

'use strict';

const AWS = require('aws-sdk');
const S3 = new AWS.S3();
const Bucket = 'yourBucket';
const fs = require('fs');
const https = require('https');

const APIKey = 'AIza...your.api.key...kIVc';

const options = {
    method: 'POST',
    host: `vision.googleapis.com`,
    path: `/v1/images:annotate?key=${APIKey}`,
    headers: {
        'Content-Type': 'application/json'
    }
}

exports.handler = (event, context, callback) => {
    const req = https.request(options, res => {
        const body = [];
        res.setEncoding('utf8');
        res.on('data', chunk => {
            body.push(chunk);
        });
        res.on('end', () => {
            console.log('results', body.join(''));
            callback(null, body.join(''));
        });
    });

    req.on('error', err => {
        console.log('problem with request:', err.message);
    });

    const params = {
        Bucket,
        Key: event.Records[0].s3.object.key
    }
    S3.getObject(params, function(err, data){
        const payload = {
            "requests": [{
                "image": {
                    "content": data.Body.toString('base64')
                },
                "features": [{
                    "type": "LABEL_DETECTION",
                    "maxResults": 10
                },{
                    "type": "TEXT_DETECTION",
                    "maxResults": 10
                }]
            }]
        };

        req.write(JSON.stringify(payload));
        req.end();
    });
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-11-01
    • 1970-01-01
    • 2021-07-21
    • 2017-02-18
    • 2020-07-16
    • 2019-01-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多