web-dev-qa-db-ja.com

PythonのAWSでラムダ関数からバイナリデータを返す方法は?

python lambdaでバイナリデータを返すことができません。サムネイル画像の node-template は正常に動作しますが、取得できません。 a python lambda to work。以下は、私のラムダからの関連する行です。print("image_data " + image_64_encode)行は、base64でエンコードされたイメージをログに出力します。

def lambda_handler(event, context):
    img_base64 = event.get('base64Image')
    if img_base64 is None:
        return respond(True, "No base64Image key")

    img = base64.decodestring(img_base64)
    name = uuid.uuid4()
    path = '/tmp/{}.png'.format(name)

    print("path " + path)

    image_result = open(path, 'wb')
    image_result.write(img)
    image_result.close()

    process_image(path)

    image_processed_path = '/tmp/{}-processed.png'.format(name)
    print("image_processed_path " + image_processed_path)
    image_processed = open(image_processed_path, 'rb')
    image_processed_data = image_processed.read()
    image_processed.close()
    image_64_encode = base64.encodestring(image_processed_data)

    print("image_data " + image_64_encode)


    return respond(False, image_64_encode)


def respond(err, res):
    return {
        'statusCode': '400' if err else '200',
        'body': res,
        'headers': {
            'Content-Type': 'image/png',
        },
        'isBase64Encoded': 'true'
    }

私が間違っていることへのポインタはありますか?

14
Horv

上記の手順をすべて実行しても、content-type = */*はすべての応答をバイナリに変換します。

私の場合:

  • Json(テキスト)を返す複数のラムダ関数、バイナリファイルを返す単一のラムダ。すべてのlambdaプロキシが有効になっています。

  • ラムダはAPIゲートウェイにあります

  • API GatewayはCloudFrontの背後にあります

ヒント:API Gateway->設定に重要な情報があることに気づきました

Binary support description

引用:

API Gatewayは、Content-TypeおよびAcceptHTTPヘッダーを調べて、本文の処理方法を決定します。

これは、Content-Type応答ヘッダーがAccept要求ヘッダーと一致する必要があることを意味します

ソリューション:

  1. APIゲートウェイのバイナリメディアタイプをMIMEタイプに設定します:image/jpg

  2. HTTPリクエストセットAccept: image/jpg

  3. HTTP応答セットContent-Type: image/jpg

{
  "isBase64Encoded": True,
  "statusCode": 200,
  "headers": { "content-type": "image/jpg"},
  "body":  base64.b64encode(content_bytes).decode("utf-8")
}
  1. 次に、リクエストから「Accept」ヘッダーを受け入れるようにCloudFrontに指示する必要があります。したがって、CloudFrontディストリビューションで、API Gatewayインスタンス(IDはクリック可能)をクリックし、CloudFrontインスタンスにリダイレクトされたら、Behaviourタブに移動し、APIのパスパターンを選択します(例:/ api/*)をクリックし、Editボタンをクリックします。

Example of path patterns

新しい画面で、ホワイトリストにAcceptヘッダーを追加する必要があります。

whitelist Accept

注1:複数のファイルタイプがある場合は、APIゲートウェイ設定のBinary Media Typesにすべて追加する必要があります

注2:serverlessから来て、ラムダをデプロイするときにバイナリタイプを設定したい場合は、この投稿を確認してください: APIゲートウェイのバイナリメディアタイプの設定 =

plugins:
  - serverless-apigw-binary

custom:
  apigwBinary:
    types:
- 'image/jpeg'

Cloudfrontのserverless.ymlファイルには、次のものが含まれている必要があります。

resources:
    WebAppCloudFrontDistribution:
      Type: AWS::CloudFront::Distribution
      Properties:
        DistributionConfig:
          ...
          CacheBehaviors:
            ...
            - 
              #API calls
              ...
              ForwardedValues:
                ...
                Headers:
                  - Authorization
                  - Accept
7
C. Dămoc

ようやくこれがわかりました。 pythonラムダからバイナリデータを返すことは可能です。

ここの指示に従ってください: https://aws.Amazon.com/blogs/compute/binary-support-for-api-integrations-with-Amazon-api-gateway/

新しいメソッドを作成する場合は、必ず「Use Lambda Proxy Integration」をcheckしてください。

また、python lambda応答が次のようになることを確認してください。

return {'isBase64Encoded'   : True,
        'statusCode'        : 200,
        'headers'           : { 'Content-Type': content_type },
        'body'              : base64_encoded_binary_data}

その後:

ルート/メソッドの問題ごとに:

apigateway update-integration-response --rest-api-id <api-id> --resource-id <res-id> --http-method POST --status-code 200 --patch-operations "[{\"op\" : \"replace\", \"path\" : \"/contentHandling\", \"value\" : \"CONVERT_TO_BINARY\"}]"

AWSコンソール。およびは、APIゲートウェイの「パンくずリスト」の例で見ることができます。

<api-id> = zdb7jsoey8
<res-id> = zy2b5g

次に、「APIをデプロイ」する必要があります。私が見つけたものから、それはAPIをデプロイした後にのみ機能しました。

展開する前に、必ず「バイナリメディアタイプ」を設定してください。

ヒント:ここに素敵なAWS Shellターミナル: https://github.com/awslabs/aws-Shell

pip install aws-Shell
11
user1495323

私が知る限り、これはPython 3.の場合も同様です。バイナリデータ(バイト)を返そうとしていますが、まったく機能しません。

また、base-64エンコーディングを使用しようとしましたが、成功しませんでした。

これは、APIゲートウェイおよびプロキシ統合との併用です。

[更新]

私はようやくこれを行う方法を実現しました。 I 有効なバイナリサポート タイプ*/*そして、これを返しました:

return({
        "isBase64Encoded": True,
        "statusCode": 200,
        "headers": {
                "content-type": "image/jpg",
        },  
        'body':  base64.b64encode(open('image.jpg', 'rb').read()).decode('utf-8')
})  
5
Kyler Laird

私は約6か月前に同じ問題に直面しました。 API Gatewayでバイナリサポート(およびJSの例)が現在ありますが、Python 2.7 Lambdaは有効なバイナリレスポンスをまだサポートしていません。Python = 3.6。

JSONラッピングのため、Base64エンコードされた応答に問題があります。クライアント側でカスタムJSONを記述して、このJSONからbase-64イメージを手動で取り出しましたが、これも不十分なソリューションでした。

結果を(CloudFrontの背後にある)S3にアップロードし、301をCloudFrontに返すことは、適切な回避策のようです。私に最適です。

2