it-swarm.com.de

Wie kann ich in AWS in Python Binärdaten aus der Lambda-Funktion zurückgeben?

Ich kann Python Lambda nicht dazu bringen, Binärdaten zurückzugeben. Das Node-Template für Thumbnail-Bilder funktioniert, aber ich kann kein Python-Lambda zum Laufen bringen. Unten sind die relevanten Zeilen aus meinem Lambda. Die Zeile print("image_data " + image_64_encode) druckt ein base64-codiertes Bild in die Protokolle.

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'
    }

Gibt es Hinweise darauf, was ich falsch mache?

7
Horv

Das Befolgen der obigen Schritte hat in meinem Fall nicht funktioniert, da die binäre Unterstützung für content-type = */* alle Antworten in binäre konvertiert.

Mein Fall:

  • Mehrere Lambda-Funktionen geben json (Text) zurück, nur ein Lambda gibt eine Binärdatei zurück. Alle haben Lambda-Proxy aktiviert.

  • Die Lambdas befinden sich in einem API-Gateway

  • Das API-Gateway befindet sich hinter CloudFront

Hinweis: Ich habe eine wichtige Information im API Gateway -> Einstellungen bemerkt

 Binary support description

Zitat:

API Gateway überprüft die Header Content-Type und Accept HTTP, um zu entscheiden, wie mit dem Body umgegangen werden soll.

Dies bedeutet, dass der Header Inhaltstyp Antwort mit dem Header Akzeptieren Anfordern übereinstimmen muss

Lösung:

  1. Setzen Sie Binäre Medientypen im API-Gateway auf Ihren MIME-Typ: image/jpg

  2. In Ihrer HTTP-Anfrage setzen Sie Accept: image/jpg

  3. In Ihrem HTTP-Antwortsatz Content-Type: image/jpg

{
  "isBase64Encoded": True,
  "statusCode": 200,
  "headers": { "content-type": "image/jpg"},
  "body":  base64.b64encode(content_bytes).decode("utf-8")
}
  1. Als Nächstes müssen wir CloudFront anweisen, die Überschrift 'Accept' von der Anfrage zu akzeptieren. Klicken Sie in der CloudFront-Distribution auf Ihre API-Gateway-Instanz (ID kann angeklickt werden) und wählen Sie nach der Umleitung zur CloudFront-Instanz unter Verhalten das Pfadmuster Ihrer API aus (Beispiel:/api/*). und klicken Sie auf Bearbeiten .

 Example of path patterns

Auf dem neuen Bildschirm müssen Sie der Whitelist die Überschrift Accept hinzufügen.

 whitelist Accept

Hinweis 1: Wenn Sie über mehrere Dateitypen verfügen, müssen Sie diese in den API-Gateway-Einstellungen unter Binary Media Types hinzufügen

Hinweis 2: Für diejenigen, die von serverless kommen und die Binärtypen bei der Bereitstellung Ihrer Lambdas festlegen möchten, überprüfen Sie diesen Beitrag: Festlegen der binären Medientypen für das API-Gateway

plugins:
  - serverless-apigw-binary

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

Die serverless.yml-Datei für Cloudfront sollte Folgendes enthalten:

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

Ich habe es endlich herausgefunden. Die Rückgabe von Binärdaten aus einem Python-Lambda ist möglich.

Befolgen Sie die Anweisungen hier: https://aws.Amazon.com/blogs/compute/binary-support-for-api-integrations-with-Amazon-api-gateway/

Stellen Sie sicher, dass Sie beim Erstellen einer neuen Methode check 'Lambda Proxy-Integration verwenden' aktivieren.

Stellen Sie außerdem sicher, dass Ihre Python-Lambda-Antwort wie folgt aussieht:

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

DANN:

Für jede Ihrer Routen-/Methodenprobleme:

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\"}]"

In der AWS-Konsole. Das und ist im API Gateway 'breadcrumbs' zu sehen, zB:

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

DANN: Sie müssen die API bereitstellen. Von dem, was ich nur fand, funktionierte es erst nach der Bereitstellung der API.

Stellen Sie vor der Bereitstellung sicher, dass Sie die 'binären Medientypen' eingerichtet haben.

Hinweis: Schönes AWS Shell-Terminal hier: https://github.com/awslabs/aws-Shell

pip install aws-Shell
8
user1495323

Soweit ich weiß, ist dies auch bei Python 3 der Fall. Ich versuche, binäre Daten (Bytes) zurückzugeben. Es funktioniert überhaupt nicht.

Ich habe auch versucht, Base-64-Codierung zu verwenden, und ich habe keinen Erfolg gehabt.

Dies erfolgt mit API-Gateway und Proxy-Integration.

[aktualisieren]

Endlich wurde mir klar, wie das geht. Ich habe die binäre Unterstützung aktiviert für den Typ */* und dann Folgendes zurückgegeben:

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

Ich hatte vor ungefähr 6 Monaten das gleiche Problem. Obwohl es nun Binärunterstützung (und Beispiele in JS) in API Gateway gibt, unterstützt Python 2.7 Lambda keine gültigen Binärantworten, da Python 3.6 nicht sicher ist.

Die Base64-codierte Antwort weist aufgrund des JSON-Wrappings Probleme auf. Ich habe auf Client-Seite einen benutzerdefinierten JS geschrieben, der das Base-64-Image manuell aus diesem JSON-Code entfernt. Dies war jedoch auch eine schlechte Lösung.

Laden Sie das Ergebnis in S3 (hinter CloudFront) hoch und geben Sie 301 an CloudFront zurück, um dieses Problem zu umgehen. Funktioniert am besten für mich.

1