2016-10-13 7 views
0

ゴール:ユーザーがS3にアップロードすると、Lambdaがファイルを取得し、分析のためにGoogle Vision APIに送信し、結果を返します。Google Vision APIを投げているAWSラムダPEM_read_bio:開始行ないしErrno :: ENAMETOOLONG

thisによれば、google-cloudにはネイティブライブラリが必要であり、ラムダが動作しているOSに対してコンパイルする必要があります。 lambda-packagerを使用するとエラーが発生しましたが、代わりにノードとNPMを含むEC2を使用してインターネット検索を開始しました。これをハックする精神の中で、それが私が主に働くようにしたのです。少なくともラムダは私にELFヘッダエラーを与えるのを止めました。

私の現在の問題は、Vision APIを呼び出す2つの方法があり、どちらも仕事とどちらも異なるエラー(ほとんど)を返さないことです。


共通コード:このコードは常に同じで、それは、関数の先頭にだ、と私は問題に焦点を当てた後のコードブロックを維持するために、それを分離しています。 detect()使用

'use strict'; 

const AWS = require('aws-sdk'); 
const S3 = new AWS.S3(); 
const Bucket = 'my-awesome-bucket'; 

const gCloudConfig = { 
    projectId: 'myCoolApp', 
    credentials: { 
     client_email: '[email protected]', 
     private_key: 'yourServiceApiPrivateKey' 
    } 
} 
const gCloud = require('google-cloud')(gCloudConfig); 
const gVision = gCloud.vision(); 

:このコードは、常にエラーError: error:0906D06C:PEM routines:PEM_read_bio:no start lineを返します。理論的には、URLは公開されているため動作するはずです。エラーの検索から、私はHTTPSのものであると考えていたので、HTTPSをHTTPに置き換えたのと同じ変形を試しましたが、同じエラーがありました。 detectLabels()を使用して

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)); 
    }); 
} 

は、このコードは、常に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からの有効な回答を得るだ​​けですばらしいことになります。皆さんが提供できる手がかりがあれば、大変感謝しています。

+0

また、誰かがシバン全体にもっと多くのGoogle Cloudを使用することを提案する前に、それは現時点ではオプションではありません。 AWSに私が気づいていないVision APIに似たものがある場合は、教えてください。 – coblr

答えて

2

他の同僚との会話では、APIのロードをすべて破棄し、google-cloudモジュールを使用することを検討するように指示しました。代わりに、curlでCloud REST APIを試して、それがうまくいくかどうかを確認する必要があります。

簡単に言えば、HTTPリクエストを作成し、Google CloudのREST APIを使用してこの問題を解決した方法を説明しました。

ここに私が今働いているラムダ関数があります。おそらくまだ調整が必要ですが、これは機能しています。

'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(); 
    }); 
} 
関連する問題