在 ASP.NET Core Blazor 中处理图像
注意
此版本不是本文的最新版本。 对于当前版本,请参阅此文的 .NET 8 版本。
本文介绍在 Blazor 应用中处理图像的常见情况。
动态设置图像源
下面的示例演示如何使用 C# 字段动态设置图像的源。
对于本部分中的示例:
从任何源获取三个图像,或右键单击以下每个图像以在本地保存它们。 对
image1.png
、image2.png
和image3.png
命名。将图像放置在应用的 Web 根目录 (
wwwroot
) 中名为images
的新文件夹中。images
文件夹的使用仅用于演示目的。 可以在喜欢的任何文件夹布局中组织图像,包括直接从wwwroot
文件夹中提供图像。
在下面的 ShowImage1
组件中:
- 图像中的源 (
src
) 动态设置为 C# 中的值imageSource
。 ShowImage
方法基于传递到方法的图像id
参数更新imageSource
字段。- 呈现的按钮使用
images
文件夹中每个可用图像(共三个)的图像参数调用ShowImage
方法。 文件名使用传递给该方法的参数组成,并匹配images
文件夹中的三个图像之一。
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# 属性来保存数据。
注意
避免直接在 Lambda 表达式中使用循环变量,如前面的 for
循环示例中的 i
。 否则,所有 Lambda 表达式将使用相同的变量,这将导致在所有 Lambda 中使用相同的值。 在局部变量中捕获该变量的值。 在上面的示例中:
- 将循环变量
i
分配到imageId
。 - 将
imageId
用于 lambda 表达式。
或者,将 foreach
循环与 Enumerable.Range 结合使用,这样就能避开上述问题:
@foreach (var imageId in Enumerable.Range(1,3))
{
<button @onclick="() => ShowImage(imageId)">
Image @imageId
</button>
}
有关详细信息,请参阅 ASP.NET Core Blazor 事件处理。
流式传输图像数据
可以使用 Blazor 的流式处理互操作功能将图像直接发送到客户端,而不是在公共 URL 托管图像。
本部分中的示例使用 JavaScript (JS) 互操作流式传输图像源数据。 以下 setImage
JS 函数接受图像的 <img>
标记 id
和数据流。 该函数执行以下步骤:
- 将提供的流读入
ArrayBuffer
。 - 创建
Blob
以包装ArrayBuffer
。 - 创建一个对象 URL,用作要显示的图像的地址。
- 通过刚创建的对象 URL 使用指定的
imageElementId
更新<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>
注意
有关生产应用的 JS 位置和建议的一般指南,请参阅 “ASP.NET CoreBlazor 应用中的 JavaScript 位置”。
以下 ShowImage2
组件:
- 为 System.Net.Http.HttpClient 和 Microsoft.JSInterop.IJSRuntime 注入服务。
- 包含用于显示图像的标记
<img>
。 - 拥有用于检索图像的 Stream 的
GetImageStreamAsync
C# 方法。 生产应用可以基于特定用户动态生成图像,或者从存储中检索图像。 以下示例检索dotnet
GitHub 存储库的 .NET 头像。 - 拥有在用户选择按钮时触发的
SetImageAsync
方法。SetImageAsync
执行下列步骤:- 从
GetImageStreamAsync
检索 Stream。 - 将 Stream 包装在 DotNetStreamReference 中,这允许将图像数据流式传输到客户端。
- 调用
setImage
JavaScript 函数,该函数接受客户端上的数据。
- 从
注意
服务器端应用使用专用的 HttpClient 服务发出请求,因此服务器端 Blazor 应用的开发人员无需执行任何操作即可注册 HttpClient 服务。 根据 Blazor 项目模板创建应用时,客户端应用提供默认的 HttpClient 服务注册。 如果客户端应用的 Program
文件中不存在 HttpClient 服务注册,请通过添加 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);
}
}
其他资源
反馈
https://aka.ms/ContentUserFeedback。
即将发布:在整个 2024 年,我们将逐步淘汰作为内容反馈机制的“GitHub 问题”,并将其取代为新的反馈系统。 有关详细信息,请参阅:提交和查看相关反馈