在 ASP.NET Core Blazor 中使用映像

注意

這不是這篇文章的最新版本。 如需目前版本,請參閱本文的 .NET 8 版本

重要

這些發行前產品的相關資訊在產品正式發行前可能會有大幅修改。 Microsoft 對此處提供的資訊,不做任何明確或隱含的瑕疵擔保。

如需目前版本,請參閱本文的 .NET 8 版本

本文說明在應用程式中使用映像的 Blazor 常見情節。

動態設定映像來源

下列範例示範如何使用 C# 欄位,動態設定映像的來源。

如需本節中的範例:

  • 從任何來源取得三個映像,或以滑鼠右鍵按一下以下每個映像,以將其儲存在本機。 將映像命名為 image1.pngimage2.pngimage3.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 的串流 Interop 功能,直接將映像傳送至用戶端,而不是將映像裝載在公用 URL。

本節中的範例會使用 JavaScript (JS) Interop 對映像來源資料進行串流。 下列 setImageJS 函式會接受映像的 <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 Core 中的 JavaScript 位置Blazor 應用程式

下列 ShowImage2 元件:

  • 插入 System.Net.Http.HttpClientMicrosoft.JSInterop.IJSRuntime 的服務。
  • 包含 <img> 標籤以顯示映像。
  • 具有 GetImageStreamAsync C# 方法以擷取映像的 Stream。 生產應用程式可能會根據特定使用者動態產生映像,或從儲存體擷取映像。 下列範例會擷取 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);
    }
}

其他資源