ASP.NET Core Blazor で画像を使用する

注意

これは、この記事の最新バージョンではありません。 現在のリリースについては、この記事の .NET 8 バージョンを参照してください。

重要

この情報はリリース前の製品に関する事項であり、正式版がリリースされるまでに大幅に変更される可能性があります。 Microsoft はここに示されている情報について、明示か黙示かを問わず、一切保証しません。

現在のリリースについては、この記事の .NET 8 バージョンを参照してください。

この記事では、Blazor アプリで画像を使用する一般的なシナリオについて説明します。

画像のソースを動的に設定する

次の例では、C# のフィールドで画像のソースを動的に設定する方法を示します。

このセクションの例では、次のことを行います。

  • 任意のソースから 3 つの画像を取得するか、次の各画像を右クリックしてそれらをローカル環境に保存します。 画像に image1.pngimage2.pngimage3.png という名前を付けます。

    コンピューター アイコン笑顔文字アイコン地球アイコン

  • アプリの Web ルート (wwwroot) の images という名前の新しいフォルダーに、画像を配置します。 images フォルダーは、デモンストレーションのためにのみ使います。 wwwroot フォルダーから直接画像を提供するなど、任意のフォルダー レイアウトに画像を整理できます。

次の ShowImage1 コンポーネントでは、以下のことを行います。

  • 画像のソース (src) は、C# の imageSource の値に動的に設定されます。
  • ShowImage メソッドは、渡された画像の id 引数に基づいて imageSource フィールドを更新します。
  • レンダリングされたボタンにより、images フォルダーで使用可能な 3 つの各画像の画像引数を指定して、ShowImage メソッドが呼び出されます。 ファイル名は、メソッドに渡された引数を使って構成され、images フォルダー内の 3 つの画像のいずれかと一致します。

ShowImage1.razor:

@page "/show-image-1"

<PageTitle>Show Image 1</PageTitle>

<h1>Show Image Example 1</h1>

@if (imageSource is not null)
{
    <p>
        <img src="@imageSource" />
    </p>
}

@for (var i = 1; i <= 3; i++)
{
    var imageId = i;
    <button @onclick="() => ShowImage(imageId)">
        Image @imageId
    </button>
}

@code {
    private string? imageSource;

    private void ShowImage(int id)
    {
        imageSource = $"images/image{id}.png";
    }
}
@page "/show-image-1"

<h1>Dynamic Image Source Example</h1>

@if (imageSource is not null)
{
    <p>
        <img src="@imageSource" />
    </p>
}

@for (var i = 1; i <= 3; i++)
{
    var imageId = i;
    <button @onclick="() => ShowImage(imageId)">
        Image @imageId
    </button>
}

@code {
    private string? imageSource;

    private void ShowImage(int id)
    {
        imageSource = $"images/image{id}.png";
    }
}
@page "/show-image-1"

<h1>Dynamic Image Source Example</h1>

@if (imageSource is not null)
{
    <p>
        <img src="@imageSource" />
    </p>
}

@for (var i = 1; i <= 3; i++)
{
    var imageId = i;
    <button @onclick="() => ShowImage(imageId)">
        Image @imageId
    </button>
}

@code {
    private string? imageSource;

    private void ShowImage(int id)
    {
        imageSource = $"images/image{id}.png";
    }
}

前の例では、C# のフィールドを使用して画像のソース データを保持していますが、C# のプロパティを使用してデータを保持することもできます。

Note

前の for ループの例の i など、ラムダ式内で直接ループ変数を使用することは避けてください。 そうしないと、すべてのラムダ式で同じ変数が使用され、すべてのラムダで同じ値が使用されることになります。 変数の値をローカル変数に取得してください。 前の例の場合:

  • ループ変数 iimageId に割り当てられます。
  • imageId はラムダ式で使用されます。

または、foreach ループと Enumerable.Range を使います。このようにすると上記の問題は発生しません。

@foreach (var imageId in Enumerable.Range(1,3))
{
    <button @onclick="() => ShowImage(imageId)">
        Image @imageId
    </button>
}

詳細については、「ASP.NET Core Blazor のイベント処理」を参照してください。

画像データのストリーミング

パブリック URL で画像をホストする代わりに、Blazor のストリーミング相互運用機能を使って、画像をクライアントに直接送信できます。

このセクションの例では、JavaScript (JS) の相互運用を使って、画像ソースのデータをストリーミングします。 次の setImageJS 関数は、画像の <img> タグ id とデータ ストリームを受け取ります。 この関数は次の手順を実行します。

  • 指定されたストリームを ArrayBuffer に読み取ります。
  • Blob を作成して、ArrayBuffer をラップします。
  • 表示するイメージのアドレスとなるオブジェクト URL を作成します。
  • 指定された imageElementId と作成したオブジェクト URL を使用して、<img> 要素を更新します。
  • メモリ リークを防ぐため、コンポーネントによる画像の使用が終わったら、関数で revokeObjectURL を呼び出してオブジェクトの URLを破棄します。
<script>
  window.setImage = async (imageElementId, imageStream) => {
    const arrayBuffer = await imageStream.arrayBuffer();
    const blob = new Blob([arrayBuffer]);
    const url = URL.createObjectURL(blob);
    const image = document.getElementById(imageElementId);
    image.onload = () => {
      URL.revokeObjectURL(url);
    }
    image.src = url;
  }
</script>

Note

JS の場所と実稼働アプリの推奨事項に関する一般的なガイダンスについては、ASP.NET Core Blazor アプリの JavaScript の位置に関する記事を参照してください。

次の ShowImage2 コンポーネントでは、次を実行します。

  • System.Net.Http.HttpClient および Microsoft.JSInterop.IJSRuntime に対してサービスを挿入します。
  • 画像を表示するための <img> タグを含みます。
  • 画像の Stream を取得する GetImageStreamAsync C# メソッドがあります。 運用アプリでは、特定のユーザーに基づいて画像を動的に生成したり、ストレージから画像を取得したりできます。 次の例では、dotnet GitHub リポジトリの .NET アバターを取得します。
  • ユーザーがボタンを選ぶとトリガーされる SetImageAsync メソッドがあります。 SetImageAsync では次の手順が実行されます。
    • GetImageStreamAsync から Stream を取得します。
    • 画像データをクライアントにストリーミングできるように、StreamDotNetStreamReference でラップします。
    • クライアント上のデータを受け取る setImage JavaScript 関数を呼び出します。

Note

サーバー側アプリは専用の HttpClient サービスを使って要求を行うので、開発者は HttpClient サービスを登録するためにサーバー側 Blazor アプリで何も行う必要はありません。 クライアント側アプリには、Blazor プロジェクト テンプレートからアプリが作成されるときに、既定の HttpClient サービス登録があります。 HttpClient サービス登録がクライアント側アプリの Program ファイルに存在しない場合は、builder.Services.AddHttpClient(); を追加することによって提供します。 詳細については、「ASP.NET Core で IHttpClientFactory を使用して HTTP 要求を行う」を参照してください。

ShowImage2.razor:

@page "/show-image-2"
@inject HttpClient Http
@inject IJSRuntime JS

<PageTitle>Show Image 2</PageTitle>

<h1>Show Image Example 2</h1>

<p>
    <img id="image" />
</p>

<button @onclick="SetImageAsync">
    Set Image
</button>

@code {
    private async Task<Stream> GetImageStreamAsync()
    {
        return await Http.GetStreamAsync(
            "https://avatars.githubusercontent.com/u/9141961");
    }

    private async Task SetImageAsync()
    {
        var imageStream = await GetImageStreamAsync();
        var dotnetImageStream = new DotNetStreamReference(imageStream);
        await JS.InvokeVoidAsync("setImage", "image", dotnetImageStream);
    }
}
@page "/show-image-2"
@inject HttpClient Http
@inject IJSRuntime JS

<h1>Stream Image Data Example</h1>

<p>
    <img id="image" />
</p>

<button @onclick="SetImageAsync">
    Set Image
</button>

@code {
    private async Task<Stream> GetImageStreamAsync()
    {
        return await Http.GetStreamAsync(
            "https://avatars.githubusercontent.com/u/9141961");
    }

    private async Task SetImageAsync()
    {
        var imageStream = await GetImageStreamAsync();
        var dotnetImageStream = new DotNetStreamReference(imageStream);
        await JS.InvokeVoidAsync("setImage", "image", dotnetImageStream);
    }
}
@page "/show-image-2"
@inject HttpClient Http
@inject IJSRuntime JS

<h1>Stream Image Data Example</h1>

<p>
    <img id="image" />
</p>

<button @onclick="SetImageAsync">
    Set Image
</button>

@code {
    private async Task<Stream> GetImageStreamAsync()
    {
        return await Http.GetStreamAsync(
            "https://avatars.githubusercontent.com/u/9141961");
    }

    private async Task SetImageAsync()
    {
        var imageStream = await GetImageStreamAsync();
        var dotnetImageStream = new DotNetStreamReference(imageStream);
        await JS.InvokeVoidAsync("setImage", "image", dotnetImageStream);
    }
}

その他のリソース