MoreBeerMorePower

Power Platform中心だけど、ノーコード/ローコード系を書いてます。

Power Automate から投稿する Adaptive Card に画像を表示する方法 (2023年版)

Adaptive Cardsに画像を表示する方法はとてもたくさんあります。どの方法でもImage要素を利用するのは共通ですが、そのプロパティであるurlになにを指定するかによってやり方とメリットデメリットがあります。

まずこれまでの方法をおさらいしましょう。

  1. 画像のURLを指定する
  2. 画像のdataUriを指定する
  3. (SharePointの場合) ThumbnailのURLを取得してurlに指定する

1. 画像のURLを指定する

この方法は非常に直感的で手軽ですが、対象の画像のURLが認証無しで表示できる必要があります。(特にモバイルアプリ)

例えばSharePointのドキュメントライブラリに格納された画像ファイルのURLをurlに設定したとします。

すると、Windowsアプリやブラウザーでは画像が表示されますが、モバイルアプリで表示した際に画像が表示されないことがわかります。

どこでもクライアントに最適化された表示が得られるAdaptive Cardでデバイスによって差がでるのは残念ですね。

2. 画像のdataUriを指定する

HTMLやSVGでも利用されるますが、画像のdataUriを利用することでもAdaptive Cardに画像を表示できます。

dataUriは data:image/png;base64,iVBORw0KGgoAAAAN.... このような文字列で、Power Automateではbase64関数 を使うことで(だいたい)得られます。

この方法の良いところは、メッセージに画像を埋め込むので認証が不要なこと (デバイスによらず表示できる)です。

しかしながら、Teamsにはメッセージのサイズ制限があるので、あまりデータ量の大きな画像を追加しようとするとメッセージサイズ超過のエラーが出ます。(大体100kBくらい?)

dataUriを利用した画像表示については以下を参照ください。

【PowerAutomate】AdaptiveCardでユーザーのプロフィール画像を送信しよう! - Qiita

これもこれでなかなか使いづらいですね。毎回画像のサイズを意識しないといけません。

3. ThumbnailのURLを取得して url に指定する

SharePointのドキュメントライブラリに保存された画像では、ファイルのプロパティを取得するとサムネイル画像のURLが含まれていることがわかります。

"{Thumbnail}":{"Large":"https://japaneast1-mediap.svc.ms/transform/thumbnail?provider=spo&inputFormat=png&cs=fFNQTw&docid=https%3a%2f%2f

このような形で、サムネイルの Large, Medium, SmallのURLが入っています。

このURL、実は認証なしで画像を表示することができます。 認証が不要なので、デバイスを問わず画像を表示できますが、このURLは有効期限があるので、しばらくすると画像が表示されなくなります。

ということで、便利なんだけど過去の投稿を見る時には少しケアが必要です。

新しい方法 : Hosted Contents の利用

さて、ここまででメリット・デメリットそれぞれある方法を紹介してきましたが、2023年最新のトレンドはこれです!!

Hosted Contents を利用して画像表示

詳細オプションを開くと表示されるこの入力ボックス、公式のDocsには情報がありません。

ユーザーとして投稿する場合に限り表示される詳細オプションです。

ここに特定の形式のJSON配列を指定すると、1~3までの問題が解消された形で画像付きのAdaptive Cardが投稿されます。

使い方

まずHosted Contentsに指定するJSON配列ですが、以下のような形式にします。

[
    {
        "@microsoft.graph.temporaryId": "1",
        "contentBytes": "/9j/4SXpRXhpZgAASUkqAAgAAAAOAAABAwABAA....",
        "contentType": "image/jpg"
    },
    {
        "@microsoft.graph.temporaryId": "2",
        "contentBytes": "iVBORw0KGgoAAAAN....",
        "contentType": "image/png"
    }

]

contentType はファイルの拡張子に応じた値を指定します。contentByte には画像のbase64文字列を指定します。 @microsoft.graph.temporaryId ですが、これはこのアクションの中で一意な文字を指定すればなんでも構いません。

Adaptive Cardの本体の中では以下のようにしてImage要素のurlにHosted Contentsで記載したtemporaryIdを使ってどの画像を表示するかを指定します。

{
    "type": "Image",
    "url": "../hostedContents/1/$value",
    "style": "default"
}

全体としては以下のようなJSONになります。

{
    "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
    "type": "AdaptiveCard",
    "version": "1.4",
    "msteams": {
        "width": "Full"
    },
    "body": [
        {
            "type": "ColumnSet",
            "columns": [
                {
                    "type": "Column",
                    "items": [
                        {
                            "type": "TextBlock",
                            "text": "Image 1",
                            "weight": "bolder"
                        },
                        {
                            "type": "Image",
                            "url": "../hostedContents/1/$value",
                            "style": "default"
                        }
                    ]
                },
                {
                    "type": "Column",
                    "items": [
                        {
                            "type": "TextBlock",
                            "text": "Image 2",
                            "weight": "bolder"
                        },
                        {
                            "type": "Image",
                            "url": "../hostedContents/2/$value",
                            "style": "person"
                        }
                    ]
                }
            ]
        }
    ]
}

../hostedContents/1/$valueを指定すると、temporaryId = 1の画像が、../hostedContents/2/$value を指定すると temporaryId =2の画像がそれぞれ表示されます。

Power Automate で contentBytesとcontentTypeを取得するには

SharePoint のドキュメントライブラリを例にします。

ファイルのコンテンツは "パスによるファイル コンテンツの取得" で取得できているものとします。

この時、contentBytesと contentTypeはそれぞれ

[
{
        "@microsoft.graph.temporaryId": "1",
        "contentBytes": "@{outputs('パスによるファイル_コンテンツの取得')?['body']?['$content']}",
        "contentType": "@{outputs('パスによるファイル_コンテンツの取得')?['body']?['$content-type']}"
    }
]

上記のように、bodyの下にある $content$content-typeで取得できます。

注意事項

Hosted Contentsで定義したコンテンツは、Adaptive Card本体の中で必ず参照されなければいけません。2個の画像をHosted Contentsに入れたら全部使ってカードを作らないといけないです。

[2023/2/23追記]

hosted contentsの上限サイズの記載がありました。(Graph APIのreference)

全体で4MBまで許容されるようです。

https://learn.microsoft.com/en-us/graph/api/chatmessage-post?view=graph-rest-1.0&tabs=http#example-6-send-a-card-with-inline-images

おわり

ということで、特に不満もなく、数MBの画像ファイルもPC・モバイル両方で表示できる方法のご紹介でした。

これ以上にいい方法はないですね!

Reference:

github.com