インライン画像を送受信する

インライン画像はメッセージの一部であり、会話の [共有 ] タブに保存されているドキュメントとして表示されるのではなく、Microsoft Teams 会話に直接表示されます。Teams は各画像をアクティビティの添付ファイルとして、画像の MIME タイプとホストされた URL または base64 データ URI として表します。

Teams SDK を使用して、ユーザーがメッセージに貼り付ける画像をダウンロードしたり、ホストされた URL やメモリ内のバイトから画像を送信したりすることができます。 OneDrive または SharePoint に保存されているドキュメントについては、「 ファイルを送受信する」を参照してください。

注:

21Vianet が運用している GCC High、DoD、Teams では、ドキュメント ファイルのワークフローがサポートされていない場合でも、エージェントは base64 画像添付ファイルを使用してメッセージに画像を含めることができます。

ユーザー エクスペリエンス

インライン イメージがどのように表示され、動作するかを理解して、ビジュアル コンテンツに適したプレゼンテーションを選択できるようにします。 ユーザーは次のことができます。

  • エージェントがメッセージ テキストと base64 画像を使用して送信する画像を、書式設定されたメッセージ テキスト内に配置します。
  • 構成されたメッセージの元の位置にレンダリングする画像を貼り付けます。
  • アダプティブ カードに含まれる画像を操作します。

スタンドアロンの画像にはホストされた添付ファイルを使用し、正確な配置には base64 HTML/XML コンテンツを使用し、画像がインタラクティブ コンテンツに属する場合はアダプティブ カードを使用します。

開発者のエクスペリエンス

バイトが格納されている場所とイメージの表示方法に基づいて、イメージ表現を選択します。 次のオプションは、この記事の実装順序と一致します。

要件 推奨されるアプローチ
メッセージに貼り付けられた画像を受信する アクティビティの添付ファイルを検査し、認証済み SDK HTTP クライアントを使用する
メッセージ テキストと横の画像を送信する ホストされた URL または base64 データ URI を使用した画像添付ファイル
書式設定されたテキスト内に画像を配置する HTML/XML コンテンツの Base64 イメージ
対話型コンテンツに画像を追加する アダプティブ カードの Image 要素

アクティビティ添付ファイル コレクションには、イメージ ペイロードと HTML レイアウト情報が含まれます。 インライン イメージは、Teams SDK ファイル アクセサーでは公開されません。

操作 個人用チャット グループ チャット チャネル 要件
インライン画像の受信 アクティビティの添付ファイルでサポート アクティビティの添付ファイルを使用する アクティビティの添付ファイルを使用する アプリの認証済み SDK HTTP クライアントを使用してダウンロードします。
インライン画像を送信する サポート サポート サポート Graph のアクセス許可やユーザー サインインは必要ありません。

インライン画像を操作する

ユーザーやエージェントが、保存されたドキュメントとしてではなく、会話で直接ビジュアル コンテンツをレンダリングする必要がある場合は、インライン画像を使用します。 認証されたアクティビティの添付ファイルを使用して、画像と画像の添付ファイルまたは HTML/XML コンテンツを受信して送信します。

インライン画像の受信

インライン イメージは、Teams SDK ファイル アクセサーを介しては公開されません。 受信メッセージには、通常、認証されたダウンロード URL を含む image/* 添付ファイルと、画像の位置を保持する text/html 添付ファイルが含まれます。

image/* 添付ファイルを正規ソースとして使用します。 HTML 添付ファイルの <img src> URL を使用して画像をダウンロードしないでください。

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Teams.Apps.Clients;
using Microsoft.Teams.Apps.Schema;

HttpClient imageClient = app.Services
    .GetRequiredService<IHttpClientFactory>()
    .CreateClient(nameof(ApiClient));

teams.OnMessage(async (context, cancellationToken) =>
{
    TeamsAttachment? image =
        context.Activity.Attachments?.FirstOrDefault(
            attachment =>
                attachment.ContentType is not null &&
                attachment.ContentType.Value.StartsWith(
                    "image/",
                    StringComparison.OrdinalIgnoreCase) &&
                attachment.ContentUrl is not null);

    if (image?.ContentUrl is not Uri contentUrl)
    {
        return;
    }

    using HttpResponseMessage response =
        await imageClient.GetAsync(
            contentUrl,
            HttpCompletionOption.ResponseHeadersRead,
            cancellationToken);

    response.EnsureSuccessStatusCode();

    byte[] bytes =
        await response.Content.ReadAsByteArrayAsync(
            cancellationToken);

    // Process the image bytes.
});

主要な API と値:

  • nameof(ApiClient): プラットフォーム認証を使用する SDK クライアントを選択します。
  • ContentType: image/* MIME タイプと大文字と小文字を区別せずに一致させます。
  • ContentUrl: 正規の認証済み画像ダウンロード URL を使用します。
  • ResponseHeadersRead: 最初に応答コンテンツをバッファリングせずに処理を開始します。
  • EnsureSuccessStatusCode: イメージの取得が失敗した場合は明示的に失敗します。
app.on('message', async ({ activity }) => {
  const image = activity.attachments?.find(
    (attachment) =>
      attachment.contentType?.toLowerCase().startsWith('image/') &&
      attachment.contentUrl
  );

  if (image?.contentUrl) {
    const response = await app.api.http.get<ArrayBuffer>(
      image.contentUrl,
      { responseType: 'arraybuffer' }
    );
    const bytes = Buffer.from(response.data);

    // Process the image bytes.
  }
});

主要な API と値:

  • activity.attachments: すべての受信メッセージの添付ファイルを検索します。
  • contentType: image/* MIME タイプと大文字と小文字を区別せずに一致させます。
  • contentUrl: 正規の認証済み画像ダウンロード URL を使用します。
  • app.api.http: SDK の認証済みクライアントでバイトをダウンロードします。
  • responseType: バイナリ イメージ コンテンツを受信するように arraybuffer を設定します。
@app.on_message
async def handle_message(ctx: ActivityContext[MessageActivity]) -> None:
    image = next(
        (
            attachment
            for attachment in (ctx.activity.attachments or [])
            if attachment.content_type
            and attachment.content_type.lower().startswith("image/")
            and attachment.content_url
        ),
        None,
    )

    if image and image.content_url:
        response = await app.api.http.get(image.content_url)
        image_bytes = response.content

        # Process the image bytes.

主要な API と値:

  • ctx.activity.attachments: すべての受信メッセージの添付ファイルを検索します。
  • content_type: image/* MIME タイプと大文字と小文字を区別せずに一致させます。
  • content_url: 正規の認証済み画像ダウンロード URL を使用します。
  • app.api.http: SDK の認証済みクライアントでバイトをダウンロードします。
  • response.content: ダウンロードされたバイナリ イメージ コンテンツにアクセスします。

可能な場合は、バイトを直接処理します。 ダウンストリーム API が必要とする場合にのみ base64 に変換し、添付ファイルの実際の MIME の種類を保持します。

インライン画像を送信する

アウトバウンド インライン イメージでは、 ContentType の画像 MIME タイプと、 ContentUrl の到達可能な HTTPS URL または base64 データ URI のいずれかを使用します。 送信では、画像は OneDrive または SharePoint にアップロードされず、Graph のアクセス許可やユーザー サインインも必要ありません。

外部から利用可能なイメージ用のホスト URL、またはアプリによって保持されている小さな画像用の base64 データを選択し、対応する送信メッセージの添付ファイルを作成します。 Teams では、次の制限のあるインライン画像がサポートされます。

極限 値
最大寸法 1024 x 1024 ピクセル
最大イメージ サイズ 1 MB
サポートされている形式 PNG、JPEG、GIF
アニメーション GIF サポート対象外
SDK の検証 未実行

警告

サポートされている寸法、サイズ、または形式以外の画像は、送信 API で受け入れることができますが、Teams クライアントではレンダリングできません。

ホスト URL から画像を送信する

画像がパブリック HTTPS エンドポイント経由で既に利用可能な場合、または画像が大きすぎて効率的に埋め込むことができない場合は、ホスト URL を使用します。 到達可能な URL と一致する MIME タイプを画像添付ファイルに追加します。

TeamsAttachment image = TeamsAttachment.CreateBuilder()
    .WithContentType(new AttachmentContentType("image/png"))
    .WithContentUrl(new Uri("https://contoso.com/charts/weekly.png"))
    .WithName("weekly.png")
    .Build();

await context.SendAsync(
    new MessageActivityInput()
        .WithText("Here is the latest chart:")
        .AddAttachment(image),
    cancellationToken);

キーのプロパティと値:

  • ContentType: ホストされたイメージのバイトに一致する MIME の種類を設定します。
  • ContentUrl: 公開されている HTTPS 画像の URL を設定します。
  • Name: 画像のオプションの表示名を追加します。
  • AddAttachment: 送信メッセージに画像を添付します。
app.on('message', async ({ send }) => {
  await send(
    new MessageActivityInput('Here is the latest chart:')
      .addAttachments({
        contentType: 'image/png',
        contentUrl: 'https://contoso.com/charts/weekly.png',
        name: 'weekly.png'
      })
  );
});

キーのプロパティと値:

  • contentType: ホストされたイメージのバイトに一致する MIME の種類を設定します。
  • contentUrl: 公開されている HTTPS 画像の URL を設定します。
  • name: 画像のオプションの表示名を追加します。
  • addAttachments: 送信メッセージに画像を添付します。
@app.on_message
async def handle_message(ctx: ActivityContext[MessageActivity]) -> None:
    await ctx.send(
        MessageActivityInput(text="Here is the latest chart:").add_attachments(
            Attachment(
                content_type="image/png",
                content_url="https://contoso.com/charts/weekly.png",
                name="weekly.png",
            )
        )
    )

キーのプロパティと値:

  • content_type: ホストされたイメージのバイトに一致する MIME の種類を設定します。
  • content_url: 公開されている HTTPS 画像の URL を設定します。
  • name: 画像のオプションの表示名を追加します。
  • add_attachments: 送信メッセージに画像を添付します。

URL は、エージェントの資格情報がなくても Teams クライアントから到達できる必要があります。 小さくない画像にはこの方法をお勧めします。

イメージ バイトを base64 として送信する

画像バイトがアプリ内にのみ存在する場合 (生成されたアイコン、サムネイル、グラフなど) は、base64 データ URI を使用します。 バイトをエンコードし、正しい MIME タイプを保持し、結果のデータ URI をメッセージに添付します。

byte[] bytes = await File.ReadAllBytesAsync(
    "./charts/weekly.png",
    cancellationToken);

string dataUri =
    $"data:image/png;base64,{Convert.ToBase64String(bytes)}";

TeamsAttachment image = TeamsAttachment.CreateBuilder()
    .WithContentType(new AttachmentContentType("image/png"))
    .WithContentUrl(new Uri(dataUri))
    .WithName("weekly.png")
    .Build();

await context.SendAsync(
    new MessageActivityInput()
        .WithText("Here is the latest chart:")
        .AddAttachment(image),
    cancellationToken);

キーのプロパティと値:

  • dataUri: 一致する MIME タイプのプレフィックス base64 バイト。
  • ContentType: データ URI と実際の画像形式を一致させます。
  • ContentUrl: 完全なデータ URI を Uri でラップします。
  • Name: 画像形式に一致するオプションのファイル名を追加します。
app.on('message', async ({ send }) => {
  const bytes = await readFile('./charts/weekly.png');

  await send(
    new MessageActivityInput('Here is the latest chart:')
      .addAttachments({
        contentType: 'image/png',
        contentUrl: `data:image/png;base64,${bytes.toString('base64')}`,
        name: 'weekly.png'
      })
  );
});

キーのプロパティと値:

  • contentUrl: 一致する MIME タイプのプレフィックス base64 バイト。
  • contentType: データ URI と実際の画像形式を一致させます。
  • bytes.toString('base64'): データ URI のイメージ バイトをエンコードします。
  • name: 画像形式に一致するオプションのファイル名を追加します。
@app.on_message
async def handle_message(ctx: ActivityContext[MessageActivity]) -> None:
    encoded = b64encode(
        Path("./charts/weekly.png").read_bytes()
    ).decode("ascii")

    await ctx.send(
        MessageActivityInput(text="Here is the latest chart:").add_attachments(
            Attachment(
                content_type="image/png",
                content_url=f"data:image/png;base64,{encoded}",
                name="weekly.png",
            )
        )
    )

キーのプロパティと値:

  • content_url: 一致する MIME タイプのプレフィックス base64 バイト。
  • content_type: データ URI と実際の画像形式を一致させます。
  • b64encode: データ URI のイメージ バイトをエンコードします。
  • name: 画像形式に一致するオプションのファイル名を追加します。

Base64 は、ペイロード サイズを約 3 分の 1 に増やします。 生成される小さな画像には使用し、大きな画像にはホスト URL を使用します。

メッセージ テキスト内に画像を配置する

HTML/XML コンテンツを使用して、画像の配置と寸法を制御します。

string encoded = Convert.ToBase64String(
    await File.ReadAllBytesAsync(
        "./charts/weekly.png",
        cancellationToken));

await context.SendAsync(
    new MessageActivityInput()
        .WithText(
            $"<div>Revenue is up." +
            $"<img src=\"data:image/png;base64,{encoded}\"/>" +
            $"Questions?</div>")
        .WithTextFormat(TextFormats.Xml),
    cancellationToken);

キーのプロパティと値:

  • src: 埋め込みイメージに base64 データ URI を使用します。
  • TextFormats.Xml: メッセージ本文内の HTML 要素を有効にします。
  • height width: 画像要素にオプションのサイズを追加します。
app.on('message', async ({ send }) => {
  const bytes = await readFile('./charts/weekly.png');
  const encoded = bytes.toString('base64');

  await send(
    new MessageActivityInput(
      `<div>Revenue is up.` +
      `<img src="data:image/png;base64,${encoded}"/>` +
      `Questions?</div>`
    ).withTextFormat('xml')
  );
});

キーのプロパティと値:

  • src: 埋め込みイメージに base64 データ URI を使用します。
  • withTextFormat('xml'): メッセージ本文で HTML 要素を有効にします。
  • height width: 画像要素にオプションのサイズを追加します。
@app.on_message
async def send_positioned_image(
    ctx: ActivityContext[MessageActivity],
) -> None:
    encoded = base64.b64encode(
        Path("./charts/weekly.png").read_bytes()
    ).decode("ascii")

    await ctx.send(
        MessageActivityInput(
            text=(
                '<div>Revenue is up.'
                f'<img src="data:image/png;base64,{encoded}"/>'
                'Questions?</div>'
            )
        ).with_text_format("xml")
    )

キーのプロパティと値:

  • src: 埋め込みイメージに base64 データ URI を使用します。
  • with_text_format("xml"): メッセージ本文で HTML 要素を有効にします。
  • height width: 画像要素にオプションのサイズを追加します。

HTTPS <img src> はアップロードまたは書き換えられません。 代わりにホストされた画像添付ファイルを使用してください。 埋め込みイメージはすべてメッセージ ペイロードにカウントされ、制限を超えるとメッセージ全体が拒否される可能性があります。

複数のスタンドアロン画像の場合は、各添付ファイルを追加し、リストやカルーセルなどのサポートされているレイアウトを選択します。 対話型コンテンツ内の画像には、アダプティブ カード Image 要素を使用します。 ストリーム応答の場合は、中間の入力アクティビティに添付ファイルが保持されないため、最後のメッセージにのみ添付ファイルを追加します。

エラーを処理する

取得エラーをイメージ検証およびレンダリング エラーとは別に処理し、ユーザーが実用的な応答を受け取れるようにします。

状態コード エラー コード 説明 開発者の処置
HTTP 4xx 認証済みイメージ要求に失敗しました プラットフォームが受信画像 URL の要求を拒否しました。 認証された SDK HTTP クライアントを使用し、応答状態を保持し、アプリがメッセージの添付ファイルにアクセスできることを確認します。
HTTP 5xx 画像サービスは利用できません Teams または添付ファイル サービスがダウンロードを完了できませんでした。 元のエラーを保持し、サービス ガイダンスに従って再試行します。
該当なし 無効な画像添付ファイル 添付ファイルに画像、MIME の種類、またはコンテンツ URL がありません。 添付ファイルをスキップして、残りのアクティビティの添付ファイルを調べます。
該当なし ホストされたイメージが使用できない Teams クライアントは、エージェントの資格情報がないと、ホストされた画像の URL に到達できません。 公開されている HTTPS URL を使用するか、base64 イメージを送信します。
該当なし イメージ レンダリングに失敗しました MIME の種類、形式、サイズ、サイズはサポートされていません。 MIME タイプをバイトと一致させ、送信前にイメージを検証します。
該当なし 拒否されたメッセージ ペイロード Base64 イメージ コンテンツによって、メッセージがペイロード制限を超えます。 画像のサイズを小さくするか、ホストされた URL を使用します。

設計ガイドラインとベスト プラクティス

これらのガイドラインを適用して、信頼性が高くアクセス可能なインライン画像エクスペリエンスを作成します。 画像コンテンツを処理または送信する前に、それらを確認してください。

  • エージェントが受信または生成した画像と、エージェントがコンテンツに対して何をしたかをユーザーに伝えます。
  • 画像の受信 URL には、認証済みの SDK HTTP クライアントを使用します。
  • 最初の添付ファイルを画像と想定するのではなく、すべての添付ファイルを検索します。
  • HTML <img src> URL ではなく、正規のダウンロード ソースとして image/* 添付ファイルを使用してください。
  • 実際のイメージ MIME タイプを保持および検証します。
  • base64 イメージを小さくし、大きなイメージにはホスト URL を優先します。
  • エージェントの資格情報がなくてもホストされるイメージの URL に到達できることを確認します。
  • 送信前に、画像のサイズ、寸法、形式を検証してください。
  • 画像がアダプティブ カードの一部である場合は、意味のある代替テキストを追加します。
  • HTML/XML は、正確な画像の配置または寸法が必要な場合にのみ使用してください。
  • 中間的な入力アクティビティには添付ファイルが添付されないため、最終的なストリーミング メッセージに添付ファイルを追加します。
  • 画像バイトや認証された添付ファイル URL はログに記録しないでください。
  • 診断のためにキャンセルを伝達し、HTTP エラーを保持します。

関連項目

これらのリソースを使用して、関連する Teams SDK イメージ API、ファイル処理、カード、およびメッセージング ガイダンスを調べます。