Sdílet prostřednictvím


Zobrazení obrázků a dokumentů v ASP.NET Core Blazor

Poznámka:

Toto není nejnovější verze tohoto článku. Aktuální verzi najdete ve verzi .NET 8 tohoto článku.

Upozorňující

Tato verze ASP.NET Core se už nepodporuje. Další informace najdete v tématu .NET a .NET Core Zásady podpory. Aktuální verzi najdete ve verzi .NET 8 tohoto článku.

Důležité

Tyto informace se týkají předběžného vydání produktu, který může být podstatně změněn před komerčním vydáním. Microsoft neposkytuje žádné záruky, výslovné ani předpokládané, týkající se zde uváděných informací.

Aktuální verzi najdete ve verzi .NET 8 tohoto článku.

Tento článek popisuje přístupy k zobrazení obrázků a dokumentů v Blazor aplikacích.

Příklady v tomto článku jsou k dispozici pro kontrolu a použití v ukázkových Blazor aplikacích:

dotnet/blazor-samples Úložiště GitHub: Přejděte do aplikace s názvem BlazorSample_BlazorWebApp (8.0 nebo novější), BlazorSample_Server (7.0 nebo starší) nebo BlazorSample_WebAssembly.

Dynamické nastavení zdroje obrázku

Následující příklad ukazuje, jak dynamicky nastavit zdroj image s polem C#.

Příklad v této části používá tři soubory obrázků s názvem image1.png, image2.pnga image3.png. Obrázky se umístí do složky pojmenované images ve webovém kořenovém adresáři aplikace (wwwroot). Použití images složky je pouze pro demonstrační účely. Statické prostředky můžete uspořádat v libovolném rozložení složky, které preferujete, včetně poskytování prostředků přímo ze wwwroot složky.

V následující komponentě ShowImage1:

  • Zdroj image (src) je dynamicky nastaven na hodnotu imageSource v jazyce C#.
  • Metoda ShowImage aktualizuje imageSource pole na základě argumentu obrázku id předaného metodě.
  • Vykreslená tlačítka volají metodu ShowImage s argumentem obrázku pro každý ze tří dostupných obrázků ve images složce. Název souboru se skládá pomocí argumentu předaného metodě a odpovídá jednomu ze tří obrázků ve images složce.

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";
    }
}

Předchozí příklad používá pole jazyka C# k uložení zdrojových dat obrázku, ale k uložení dat můžete použít také vlastnost jazyka C#.

Nepoužívejte proměnnou smyčky přímo ve výrazu lambda, například i v předchozím příkladu smyčky for . V opačném případě se stejná proměnná používá ve všech výrazech lambda, což vede k použití stejné hodnoty ve všech výrazech lambda. Zachyťte hodnotu proměnné v místní proměnné. V předchozím příkladu:

  • Proměnná i smyčky je přiřazena .imageId
  • imageId se používá ve výrazu lambda.

Alternativně použijte smyčku foreach s Enumerable.Range, která netrpí předchozím problémem:

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

Další informace o výrazech lambda s zpracováním událostí najdete v tématu ASP.NET zpracování událostí CoreBlazor.

Streamování dat obrázků nebo dokumentů

Obrázek nebo jiný typ dokumentu, například PDF, je možné přímo přenést do klienta pomocí Blazorfunkcí komunikace streamování místo hostování souboru na veřejné adrese URL.

Příklad v této části streamuje zdrojová data pomocí zprostředkovatele komunikace JavaScriptu (JS). setSourceJS Následující funkce:

  • Lze použít ke streamování obsahu pro následující prvky: , , , , , <link>, <object>, , <script>, <style>, a <track>. <img><iframe><embed><body>
  • Přijímá prvek id pro zobrazení obsahu souboru, datového proudu pro dokument, typ obsahu a název prvku zobrazení.

Funkce:

  • Načte zadaný datový proud do objektu ArrayBuffer.
  • Blob Vytvoří pro zabalení objektu ArrayBufferblob nastavení typu obsahu objektu blob.
  • Vytvoří adresu URL objektu, která bude sloužit jako adresa pro zobrazení dokumentu.
  • Nastaví název elementu (title) z parametru title a nastaví zdroj elementu (src) z adresy URL vytvořeného objektu.
  • Aby se zabránilo nevracení paměti, funkce volá revokeObjectURL , aby po načtení prvku prostředek (load událost) zlikvidovaly adresu URL objektu.
<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>

Poznámka:

Obecné pokyny k JS umístění a doporučení pro produkční aplikace najdete v tématu o umístění JavaScriptu v aplikacích ASP.NET CoreBlazor.

ShowImage2 Následující komponenta:

  • Vloží služby pro a System.Net.Http.HttpClient Microsoft.JSInterop.IJSRuntime.
  • <img> Obsahuje značku pro zobrazení obrázku.
  • Má metodu jazyka GetImageStreamAsync C#, která načte Stream image. Produkční aplikace může dynamicky generovat image na základě konkrétního uživatele nebo načíst image z úložiště. Následující příklad načte avatar .NET pro dotnet úložiště GitHub.
  • Má metodu SetImageAsync , která se aktivuje na výběru tlačítka uživatelem. SetImageAsync provede následující kroky:
    • Načte Stream z GetImageStreamAsync.
    • Zabalí do objektu Stream DotNetStreamReference, který umožňuje streamování dat obrázku do klienta.
    • Vyvolá javascriptovou setSource funkci, která přijímá data v klientovi.

Poznámka:

Aplikace na straně serveru používají k odesílání požadavků vyhrazenou HttpClient službu, takže vývojář aplikace na straně Blazor serveru nevyžaduje žádnou akci k registraci HttpClient služby. Aplikace na straně klienta mají při vytváření aplikace ze Blazor šablony projektu výchozí HttpClient registraci služby. HttpClient Pokud v souboru aplikace na straně klienta není k dispozici Program registrace služby, zadejte ji přidáním builder.Services.AddHttpClient();. Další informace najdete v tématu Vytváření požadavků HTTP pomocí IHttpClientFactory v ASP.NET Core.

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");
    }
}

Následující ShowFile komponenta načte textový soubor (files/quote.txt) nebo pdf soubor (files/quote.pdf) do elementu <iframe> (dokumentace k MDN).

Upozornění

Použití elementu <iframe> v následujícím příkladu je bezpečné a nevyžaduje sandboxing , protože obsah je načten z aplikace, což je důvěryhodný zdroj.

Při načítání obsahu z nedůvěryhodného zdroje nebo vstupu uživatele by nesprávně implementovaný <iframe> prvek riskoval vytváření ohrožení zabezpečení.

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);
    }
}

Další materiály