ASP.NET Core Blazor でイメージとドキュメントを表示する
Note
これは、この記事の最新バージョンではありません。 現在のリリースについては、この記事の .NET 8 バージョンを参照してください。
警告
このバージョンの ASP.NET Core はサポート対象から除外されました。 詳細については、「.NET および .NET Core サポート ポリシー」を参照してください。 現在のリリースについては、この記事の .NET 8 バージョンを参照してください。
重要
この情報はリリース前の製品に関する事項であり、正式版がリリースされるまでに大幅に変更される可能性があります。 Microsoft はここに示されている情報について、明示か黙示かを問わず、一切保証しません。
現在のリリースについては、この記事の .NET 8 バージョンを参照してください。
この記事では、 Blazor アプリで画像とドキュメントを表示する方法について説明します。
この記事の例は、次の Blazor サンプル アプリで検査および使用できます。
dotnet/blazor-samples
GitHub リポジトリ: BlazorSample_BlazorWebApp
(8.0 以降)、 BlazorSample_Server
(7.0 以前)、または BlazorSample_WebAssembly
という名前のアプリに移動します。
画像のソースを動的に設定する
次の例では、C# のフィールドで画像のソースを動的に設定する方法を示します。
このセクションの例では、image1.png
、image2.png
、および image3.png
という名前の 3 つのイメージ ファイルを使用します。 アプリの 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"
<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# のプロパティを使用してデータを保持することもできます。
前の for
ループの例の i
など、ラムダ式内で直接ループ変数を使用することは避けてください。 そうしないと、すべてのラムダ式で同じ変数が使用され、すべてのラムダで同じ値が使用されることになります。 変数の値をローカル変数に取得してください。 前の例の場合:
- ループ変数
i
はimageId
に割り当てられます。 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 のストリーミング相互運用機能を使って、画像やドキュメントの種類 (PDFなど) をクライアントに直接送信できます。
このセクションの例では、JavaScript (JS) の相互運用を使って、画像ソースのデータをストリーミングします。 次の setSource
JS 関数:
<body>
、<embed>
、<iframe>
、<img>
、<link>
、<object>
、<script>
、<style>
、<track>
の各要素のコンテンツをストリーミングするために使用できます。- ファイルの内容、ドキュメントのデータ ストリーム、コンテンツ タイプ、および表示要素のタイトルを表示する要素
id
を受け入れます。
関数は、次のことを行います。
- 指定されたストリームを
ArrayBuffer
に読み取ります。 - BLOB のコンテンツ タイプを設定して、
ArrayBuffer
をラップするBlob
を作成します。 - 表示するドキュメントのアドレスとなるオブジェクト URL を作成します。
title
パラメーターから要素のタイトル (title
) を設定し、作成されたオブジェクト URL から要素のソース (src
) を設定します。- メモリ リークを防ぐために、関数は
revokeObjectURL
を呼び出して、要素がリソース (load
イベント) を読み込んだ後にオブジェクト URL を破棄します。
<script>
window.setSource = async (elementId, stream, contentType, title) => {
const arrayBuffer = await stream.arrayBuffer();
let blobOptions = {};
if (contentType) {
blobOptions['type'] = contentType;
}
const blob = new Blob([arrayBuffer], blobOptions);
const url = URL.createObjectURL(blob);
const element = document.getElementById(elementId);
element.title = title;
element.onload = () => {
URL.revokeObjectURL(url);
}
element.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 を取得します。- 画像データをクライアントにストリーミングできるように、Stream を DotNetStreamReference でラップします。
- クライアント上のデータを受け取る
setSource
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>
<button @onclick="SetImageAsync">
Set Image
</button>
<div class="p-3">
<img id="avatar" />
</div>
@code {
private async Task<Stream> GetImageStreamAsync() =>
await Http.GetStreamAsync("https://avatars.githubusercontent.com/u/9141961");
private async Task SetImageAsync()
{
var imageStream = await GetImageStreamAsync();
var strRef = new DotNetStreamReference(imageStream);
await JS.InvokeVoidAsync("setSource", "avatar", strRef, "image/png",
".NET GitHub avatar");
}
}
@page "/show-image-2"
@inject HttpClient Http
@inject IJSRuntime JS
<PageTitle>Show Image 2</PageTitle>
<h1>Show Image Example 2</h1>
<button @onclick="SetImageAsync">
Set Image
</button>
<div class="p-3">
<img id="avatar" />
</div>
@code {
private async Task<Stream> GetImageStreamAsync() =>
await Http.GetStreamAsync("https://avatars.githubusercontent.com/u/9141961");
private async Task SetImageAsync()
{
var imageStream = await GetImageStreamAsync();
var strRef = new DotNetStreamReference(imageStream);
await JS.InvokeVoidAsync("setSource", "avatar", strRef, "image/png",
".NET GitHub avatar");
}
}
@page "/show-image-2"
@inject HttpClient Http
@inject IJSRuntime JS
<h1>Show Image Example 2</h1>
<button @onclick="SetImageAsync">
Set Image
</button>
<div class="p-3">
<img id="avatar" />
</div>
@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 strRef = new DotNetStreamReference(imageStream);
await JS.InvokeVoidAsync("setSource", "avatar", strRef, "image/png",
".NET GitHub avatar");
}
}
@page "/show-image-2"
@inject HttpClient Http
@inject IJSRuntime JS
<h1>Show Image Example 2</h1>
<button @onclick="SetImageAsync">
Set Image
</button>
<div class="p-3">
<img id="avatar" />
</div>
@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 strRef = new DotNetStreamReference(imageStream);
await JS.InvokeVoidAsync("setSource", "avatar", strRef, "image/png",
".NET GitHub avatar");
}
}
次の ShowFile
コンポーネントは、テキスト ファイル (files/quote.txt
) または PDF ファイル (files/quote.pdf
) を <iframe>
要素 (MDN ドキュメント) に読み込みます。
注意事項
次の例の <iframe>
要素の使用は安全であり、コンテンツは信頼できるソースであるアプリから読み込まれるため、サンドボックスは必要ありません。
信頼されていないソースまたはユーザー入力からコンテンツを読み込むと、不適切に実装された <iframe>
要素によってセキュリティの脆弱性が発生するリスクがあります。
ShowFile.razor
:
@page "/show-file"
@inject NavigationManager Navigation
@inject HttpClient Http
@inject IJSRuntime JS
<PageTitle>Show File</PageTitle>
<div class="d-flex flex-column">
<h1>Show File Example</h1>
<div class="mb-4">
<button @onclick="@(() => ShowFileAsync("files/quote.txt",
"General Ravon quote (text file)"))">
Show text ('quote.txt')
</button>
<button @onclick="@(() => ShowFileAsync("files/quote.pdf",
"General Ravon quote (PDF file)"))">
Show PDF ('quote.pdf')
</button>
</div>
<iframe id="iframe" style="height: calc(100vh - 200px)" />
</div>
@code
{
private async Task<(Stream, string?)> DownloadFileAsync(string url)
{
var absoluteUrl = Navigation.ToAbsoluteUri(url);
Console.WriteLine($"Downloading file from {absoluteUrl}");
var response = await Http.GetAsync(absoluteUrl);
string? contentType = null;
if (response.Content.Headers.TryGetValues("Content-Type", out var values))
{
contentType = values.FirstOrDefault();
}
return (await response.Content.ReadAsStreamAsync(), contentType);
}
private async Task ShowFileAsync(string url, string title)
{
var (fileStream, contentType) = await DownloadFileAsync(url);
var strRef = new DotNetStreamReference(fileStream);
await JS.InvokeVoidAsync("setSource", "iframe", strRef, contentType, title);
}
}
@page "/show-file"
@inject NavigationManager Navigation
@inject HttpClient Http
@inject IJSRuntime JS
<PageTitle>Show File</PageTitle>
<div class="d-flex flex-column">
<h1>Show File Example</h1>
<div class="mb-4">
<button @onclick="@(() => ShowFileAsync("files/quote.txt",
"General Ravon quote (text file)"))">
Show text ('quote.txt')
</button>
<button @onclick="@(() => ShowFileAsync("files/quote.pdf",
"General Ravon quote (PDF file)"))">
Show PDF ('quote.pdf')
</button>
</div>
<iframe id="iframe" style="height: calc(100vh - 200px)" />
</div>
@code
{
private async Task<(Stream, string?)> DownloadFileAsync(string url)
{
var absoluteUrl = Navigation.ToAbsoluteUri(url);
Console.WriteLine($"Downloading file from {absoluteUrl}");
var response = await Http.GetAsync(absoluteUrl);
string? contentType = null;
if (response.Content.Headers.TryGetValues("Content-Type", out var values))
{
contentType = values.FirstOrDefault();
}
return (await response.Content.ReadAsStreamAsync(), contentType);
}
private async Task ShowFileAsync(string url, string title)
{
var (fileStream, contentType) = await DownloadFileAsync(url);
var strRef = new DotNetStreamReference(fileStream);
await JS.InvokeVoidAsync("setSource", "iframe", strRef, contentType, title);
}
}
@page "/show-file"
@inject NavigationManager NavigationManager
@inject HttpClient Http
@inject IJSRuntime JS
<div class="d-flex flex-column">
<h1>Show File Example</h1>
<div class="mb-4">
<button @onclick="@(() => ShowFileAsync("files/quote.txt",
"General Ravon quote (text file)"))">
Show text ('quote.txt')
</button>
<button @onclick="@(() => ShowFileAsync("files/quote.pdf",
"General Ravon quote (PDF file)"))">
Show PDF ('quote.pdf')
</button>
</div>
<iframe id="iframe" style="height: calc(100vh - 200px)" />
</div>
@code
{
private async Task<(Stream, string?)> DownloadFileAsync(string url)
{
var absoluteUrl = NavigationManager.ToAbsoluteUri(url);
Console.WriteLine($"Downloading file from {absoluteUrl}");
var response = await Http.GetAsync(absoluteUrl);
string? contentType = null;
if (response.Content.Headers.TryGetValues("Content-Type", out var values))
{
contentType = values.FirstOrDefault();
}
return (await response.Content.ReadAsStreamAsync(), contentType);
}
private async Task ShowFileAsync(string url, string title)
{
var (fileStream, contentType) = await DownloadFileAsync(url);
var strRef = new DotNetStreamReference(fileStream);
await JS.InvokeVoidAsync("setSource", "iframe", strRef, contentType, title);
}
}
@page "/show-file"
@inject NavigationManager NavigationManager
@inject HttpClient Http
@inject IJSRuntime JS
<div class="d-flex flex-column">
<h1>Show File Example</h1>
<div class="mb-4">
<button @onclick="@(() => ShowFileAsync("files/quote.txt",
"General Ravon quote (text file)"))">
Show text ('quote.txt')
</button>
<button @onclick="@(() => ShowFileAsync("files/quote.pdf",
"General Ravon quote (PDF file)"))">
Show PDF ('quote.pdf')
</button>
</div>
<iframe id="iframe" style="height: calc(100vh - 200px)" />
</div>
@code
{
private async Task<(Stream, string?)> DownloadFileAsync(string url)
{
var absoluteUrl = NavigationManager.ToAbsoluteUri(url);
Console.WriteLine($"Downloading file from {absoluteUrl}");
var response = await Http.GetAsync(absoluteUrl);
string? contentType = null;
if (response.Content.Headers.TryGetValues("Content-Type", out var values))
{
contentType = values.FirstOrDefault();
}
return (await response.Content.ReadAsStreamAsync(), contentType);
}
private async Task ShowFileAsync(string url, string title)
{
var (fileStream, contentType) = await DownloadFileAsync(url);
var strRef = new DotNetStreamReference(fileStream);
await JS.InvokeVoidAsync("setSource", "iframe", strRef, contentType, title);
}
}
その他のリソース
ASP.NET Core