How to: Bilder von Azure Logic Apps an eine Custom API verschicken – als Multipart From-Data

Jan 9, 2023 Entwicklung
[Reading Time: 5 minutes]

Warum Bilder an eine API versenden?

Für ein kleines privates Projekt wollte ich für generierte Bilder in Azure Blobstorage eine Logic App triggern, die diese dann an Teams mit AdaptiveCards anzeigen sollte.

Das Problem: manche der Bilder waren einfach größer als die erlaubten 25KB Payload der Adaptive Card.

Welche Lösungen sind möglich: sicher sehr viele.

  • ich könnte eine URL auf das Bild in der AdaptiveCard angeben. Da ich aber das Bild aber auch noch anderweitig verändern und weiternutzen möchte, ist das nicht die beste Option.
  • Ich könnte die Bilder gleich so klein generieren, dass der Payload nicht überschritten wird. Allerdings hätte ich dann nicht mehr die Größe, dich ich für andere Aufgaben benötige.
  • Doppelt in unterschiedlichen Größen anlegen? Klar, und wenn ich dann wieder eine andere Größe brauche, einfach noch eine weitere Größe generieren und tausende Redundanzen aufbauen? Nope!
  • Das Bild an die Azure Cognitive Services schicken und als Thumbnail zurück bekommen. Wirklich gute Idee, habe ich aber dennoch nicht gemacht, weil ich bereits eine eigene API habe, die sowas schon erledigt und weniger kostenintensiv und “aufwendig” ist.
  • Also an eine eigene API schicken..?!

Ich habe mich in meinem Projekt dafür entschieden, ein Image an meine API zu senden. Allerdings erwaret die das Bild als Datei welches ich mit dem Content-Type MultiPart/Form-Data abliefern muss. Im Nachfolgenden beschreibe ich dir gern, wie ich das gemacht habe, was auch für jeden anderen Dateitype funktioniert.

Ansprechen einer API mit cURL

Um das Bild an eine API zu senden, kann man die HTTP Action zurück greifen. Über diese wird eine normaler Http-Request auf eien URI ausgeführt. D.h. also, man kann auch alles über eine HTTP Action schicken, was man auch mit einem normalen cURL-Befehl könnte. JA! Nur wie ist schwierig, da in der Action nicht alles “klickbar” ist.

Welche Option haben wir also? Lass uns mal anschauen, wie ein wir das mit cURL machen würden:

curl -F "image=@${FILENAME}" -F "size=400" $URL

Das Kommando sendet eine Bilddatei (der Filename kommt aus der Environment variable FILENAME) als Form-data mit dem Feldnamen “image”. Als zweiten Parameter setze ich die gewünschte Größe und schicke das alles an die url $URL

cURL nach HTTP übersetzen

Hilft uns das Wissen darüber? Nur bedingt! Lass mal schauen, wie das als HTTP Request aussehen würde:

POST / HTTP/1.1
Host: $URL
Content-Type: multipart/form-data; boundary=--------------------------484040840196266074159071
Content-Length: [length of the request body]

----------------------------484040840196266074159071
Content-Disposition: form-data; name="image"; filename="[FILENAME]"
Content-Type: application/octet-stream

[binary data for the file specified in the filename field]
----------------------------484040840196266074159071
Content-Disposition: form-data; name="size"

400
----------------------------484040840196266074159071--

Was auffällt ist “boundary”. dieser “Marker” läßt den HTTP Interpreter wissen, dass nun die Form-Data gelesen werden können. ein “Boundary” startet mit zwei — (Strich).

Anschließend begint ein Form-Feld mit ‘Content-Disposition’ und der Angebe des Feldnamens. Es werden natürlich immer die Content-Types erwartet (nicht aber immer zwangsweise).

Jedes Feld wird mit einem Start-Boundary nacheinander aufgeführt. Für das Versenden eienr Datei, wird einfach deren Inhalt nach einer leeren Zeile (wie du im ersten Boundary sehen kannst) eingefügt.

die Form-Data schließt du mit –<boundary-id>– ab. in Meinem Beispiel ist das –484040840196266074159071– (nicht verwirren lassen… die boundary-id muss einfach unique sein – darf also nicht im Text der Datei vorkommen)

Den HTTP Request in die HTTP Action übertragen

HTTP Action ausgefüllt

Hier siehst du, dass ich eine Post Methode verwende.

Unter URI gebe ich meine Custom API Url an.

Bei “Headers” packe ich den Content-Type für Multipart/Form-Data rein, was dem oberen HTTP Request entspricht. mein Boundary habe ich ‘testboundary’ genannt. Es gibt keine wirklichen Regeln für diesen Namen – wichtig: darf nicht im nachfolgenden Content verwendet werden. (was bei einem Bild nicht vorkommen dürfte 🙂 )

Im Body kommt alles rein, was ich dir oben im HTTP Request erklärt habe.

Was du noch nicht weißt ist, in “Outputs” habe ich das File in Vorbereitung auf die AdaptiveCard als Base64 codiert – es wird also immer an Teams eine komplettes Bild versendet.

In meiner Custom API, die auf Azure Container App läuft, lese ich nun das File ein verkleinere/vergrößere das Bild und sende es wieder zurück.

Im Anschluß kann ich das Bild nun entspannt weiter verarbeiten.

Ich hoffe das konnte dir etwas weiterhelfen. Wenn nicht, kannst du immernoch versuchen andere Wege zu gehen. Ich hatte überlegt mein API an die Möglichekeiten an zu passen einen Base64 String zu empfangen. Oder auch nochmal in Bloblstorage temporär abzulegen. Das erschien mir für meine Zwecke einfach nicht gut – vielleicht passt das bei dir aber besser. Who knows!

Von Thomas

Als Chief Technology Officer bei Xpirit Deutschland. Ich bin dafür verantwortlich, die Produktivität unserer Kunden durch einen Full-Stack von Dev und Technologie in der heutigen Zeit zu steigern. Dabei kümmere ich mich nicht nur um Technologien aus Microsofts Stack wie Azure, AI und IoT, sondern auch um die Bereitstellung von Qualität und Expertise mit DevOps

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.