Bagikan melalui


Menampilkan gambar dan dokumen di ASP.NET Core Blazor

Catatan

Ini bukan versi terbaru dari artikel ini. Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.

Peringatan

Versi ASP.NET Core ini tidak lagi didukung. Untuk informasi selengkapnya, lihat Kebijakan Dukungan .NET dan .NET Core. Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.

Penting

Informasi ini berkaitan dengan produk pra-rilis yang mungkin dimodifikasi secara substansial sebelum dirilis secara komersial. Microsoft tidak memberikan jaminan, tersirat maupun tersurat, sehubungan dengan informasi yang diberikan di sini.

Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.

Artikel ini menjelaskan pendekatan untuk menampilkan gambar dan dokumen di Blazor aplikasi.

Contoh dalam artikel ini tersedia untuk diperiksa dan digunakan dalam Blazor aplikasi sampel:

dotnet/blazor-samples Repositori GitHub: Navigasikan ke aplikasi bernama BlazorSample_BlazorWebApp (8.0 atau yang lebih baru), BlazorSample_Server (7.0 atau yang lebih lama), atau BlazorSample_WebAssembly.

Mengatur sumber gambar secara dinamis

Contoh berikut menunjukkan cara mengatur sumber gambar secara dinamis dengan bidang C#.

Contoh di bagian ini menggunakan tiga file gambar, bernama image1.png, image2.png, dan image3.png. Gambar ditempatkan dalam folder bernama images di akar web aplikasi (wwwroot). Penggunaan images folder hanya untuk tujuan demonstrasi. Anda dapat mengatur aset statis dalam tata letak folder apa pun yang Anda sukai, termasuk menyajikan aset langsung dari wwwroot folder.

Dalam komponen ShowImage1 berikut:

  • Sumber gambar (src) secara dinamis diatur ke nilai imageSource dalam C#.
  • Metode ShowImage memperbarui imageSource bidang berdasarkan argumen gambar id yang diteruskan ke metode .
  • Tombol yang dirender memanggil ShowImage metode dengan argumen gambar untuk masing-masing dari tiga gambar yang images tersedia di folder. Nama file terdiri menggunakan argumen yang diteruskan ke metode dan cocok dengan salah satu dari tiga gambar dalam images folder.

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

Contoh sebelumnya menggunakan bidang C# untuk menyimpan data sumber gambar, tetapi Anda juga dapat menggunakan properti C# untuk menyimpan data.

Catatan

Hindari menggunakan variabel loop langsung dalam ekspresi lambda, seperti i dalam contoh perulangan sebelumnya for . Jika tidak, variabel yang sama digunakan oleh semua ekspresi lambda, yang menghasilkan penggunaan nilai yang sama di semua lambda. Ambil nilai variabel dalam variabel lokal. Dalam contoh sebelumnya:

  • Variabel i perulangan ditetapkan ke imageId.
  • imageId digunakan dalam ekspresi lambda.

Atau, gunakan perulangan foreach dengan Enumerable.Range, yang tidak menderita masalah sebelumnya:

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

Untuk informasi selengkapnya, lihat penanganan peristiwa ASP.NET CoreBlazor.

Mengalirkan data gambar atau dokumen

Gambar atau jenis dokumen lainnya, seperti PDF, dapat langsung ditransmisikan ke klien menggunakan Blazorfitur interop streaming alih-alih menghosting file di URL publik.

Contoh di bagian ini mengalirkan data sumber menggunakan interop JavaScript (JS). Fungsi berikut setSourceJS :

  • Dapat digunakan untuk mengalirkan konten untuk elemen berikut: <body>, , , <embed><iframe>, <img><link>, <object>, <script>, , <style>, dan <track>.
  • Menerima elemen id untuk menampilkan konten file, aliran data untuk dokumen, jenis konten, dan judul untuk elemen tampilan.

Fungsi :

  • Membaca aliran yang disediakan ke dalam ArrayBuffer.
  • Membuat untuk membungkus Blob ArrayBuffer, mengatur jenis konten blob.
  • Membuat URL objek untuk berfungsi sebagai alamat dokumen yang akan ditampilkan.
  • Atur judul elemen (title) dari title parameter dan mengatur sumber elemen (src) dari URL objek yang dibuat.
  • Untuk mencegah kebocoran memori, fungsi memanggil revokeObjectURL untuk membuang URL objek setelah elemen memuat sumber daya (load peristiwa).
<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>

Catatan

Untuk panduan umum tentang JS lokasi dan rekomendasi kami untuk aplikasi produksi, lihat Lokasi JavaScript di aplikasi ASP.NET CoreBlazor.

Komponen berikut ShowImage2 :

  • Menyuntikkan layanan untuk dan System.Net.Http.HttpClient Microsoft.JSInterop.IJSRuntime.
  • <img> Menyertakan tag untuk menampilkan gambar.
  • Memiliki GetImageStreamAsync metode C# untuk mengambil Stream gambar. Aplikasi produksi dapat secara dinamis menghasilkan gambar berdasarkan pengguna tertentu atau mengambil gambar dari penyimpanan. Contoh berikut mengambil avatar .NET untuk dotnet repositori GitHub.
  • Memiliki SetImageAsync metode yang dipicu pada pilihan tombol oleh pengguna. SetImageAsync lakukan langkah-langkah berikut:
    • Mengambil Stream dari GetImageStreamAsync.
    • Membungkus Stream dalam DotNetStreamReference, yang memungkinkan streaming data gambar ke klien.
    • Memanggil setSource fungsi JavaScript, yang menerima data pada klien.

Catatan

Aplikasi sisi server menggunakan layanan khusus HttpClient untuk membuat permintaan, sehingga tidak ada tindakan yang diperlukan oleh pengembang aplikasi sisi Blazor server untuk mendaftarkan HttpClient layanan. Aplikasi sisi klien memiliki pendaftaran layanan default HttpClient saat aplikasi dibuat dari Blazor templat proyek. HttpClient Jika pendaftaran layanan tidak ada dalam Program file aplikasi sisi klien, berikan dengan menambahkan builder.Services.AddHttpClient();. Untuk informasi lebih lanjut, lihat Membuat permintaan HTTP menggunakan IHttpClientFactory di 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()
    {
        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");
    }
}
@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");
    }
}

Komponen berikut ShowFile memuat file teks (files/quote.txt) atau file PDF (files/quote.pdf) ke dalam <iframe> elemen (dokumentasi MDN).

Perhatian

Penggunaan <iframe> elemen dalam contoh berikut aman dan tidak memerlukan [sandboxing](https://developer.mozilla.org/docs/Web/HTML/Element/iframe#sandbox) karena konten dimuat dari aplikasi, sumber tepercaya.

Saat memuat konten dari sumber atau input pengguna yang tidak tepercaya, elemen yang diimplementasikan <iframe> dengan tidak benar berisiko menciptakan kerentanan keamanan.

ShowFile.razor:

@page "/show-file"
@inject NavigationManager NavigationManager
@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 = 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);
    }
}
@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);
    }
}

Sumber Daya Tambahan: