Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Примечание.
Это не последняя версия этой статьи. В текущем релизе см. версию .NET 9 этой статьи.
Предупреждение
Эта версия ASP.NET Core больше не поддерживается. Дополнительные сведения см. в политике поддержки .NET и .NET Core. В текущем выпуске см. версию .NET 9 этой статьи.
Внимание
Эта информация относится к предварительному выпуску продукта, который может быть существенно изменен до его коммерческого выпуска. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.
В текущем релизе смотрите: версию этой статьи .NET 9.
В этой статье описываются подходы к отображению изображений и документов в Blazor приложениях.
Примеры, приведенные в этой статье, доступны для проверки и использования в Blazor примерах приложений:
dotnet/blazor-samples
Репозиторий GitHub: перейдите к приложению с именем BlazorSample_BlazorWebApp
(8.0 или более поздней версии), BlazorSample_Server
(7.0 или более ранней версии) или BlazorSample_WebAssembly
.
Динамическое задание источника изображения
В следующем примере показано, как динамически задать источник изображения с помощью поля C#.
В примере в этом разделе используются три файла изображения, именованные image1.png
, image2.png
и image3.png
. Изображения помещаются в папку с именем images
в корневом каталоге веб-приложения (wwwroot
). Папка images
используется только для демонстрации. Статические ресурсы можно упорядочить в любой структуре папок на ваш выбор, включая возможность напрямую использовать ресурсы из папки wwwroot
.
В следующем компоненте ShowImage1
:
- Источнику изображения (
src
) динамически присваивается значениеimageSource
в C#. - Метод
ShowImage
обновляет полеimageSource
на основе аргумента изображенияid
, переданного в метод. - Отрисованные кнопки вызывают метод
ShowImage
с аргументом изображения для каждого из трех доступных изображений в папкеimages
. Имя файла состоит из аргумента, переданного в метод, и соответствует одному из трех изображений в папке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"
<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#.
Избегайте использования переменной цикла непосредственно в лямбда-выражении, например i
в предыдущем for
примере цикла. В противном случае одна и та же переменная будет использоваться во всех лямбда-выражениях, в результате чего значение будет одинаковым во всех лямбда-выражениях. Сохраните значение переменной в локальной переменной. В предыдущем примере:
- Переменной цикла
i
присваивается значениеimageId
. -
imageId
используется в лямбда-выражении.
В качестве альтернативы используйте цикл foreach
с Enumerable.Range, который не затронула предыдущая проблема:
@foreach (var imageId in Enumerable.Range(1, 3))
{
<button @onclick="() => ShowImage(imageId)">
Image @imageId
</button>
}
Дополнительные сведения о лямбда-выражениях с обработкой событий см. в разделе Blazor Core.
Передача данных изображения или документа
Изображение или другой тип документа, например PDF, можно напрямую передать клиенту с помощью Blazorфункций потокового взаимодействия вместо размещения файла по общедоступному URL-адресу.
Пример в этом разделе передает данные в потоке с использованием взаимодействия JavaScript (JS). Следующая функция setSource
JS:
- Можно использовать для потоковой передачи содержимого для следующих элементов:
<body>
,<embed>
<iframe>
<img>
,<link>
,<object>
<script>
<style>
и .<track>
- Принимает элемент
id
для отображения содержимого файла, потока данных для документа, типа контента и заголовка элемента отображения.
Функция :
- Читает предоставленный поток в
ArrayBuffer
. - Создает
Blob
для оборачиванияArrayBuffer
, устанавливая тип содержимого для большого двоичного объекта. - Создает URL-адрес объекта, который будет служить в качестве адреса для отображения документа.
- Задайте заголовок элемента (
title
) с помощью параметраtitle
и источник элемента (src
) с помощью URL-адреса созданного объекта. - Чтобы предотвратить утечки памяти, функция вызывает
revokeObjectURL
для освобождения URL-адреса объекта после того, как элемент загрузит ресурс (load
событие).
<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>
Примечание.
Для общих рекомендаций по JS расположению и нашим советам для производственных приложений см. статью Расположение JavaScript в приложениях ASP.NET CoreBlazor.
Приведенный ниже компонент ShowImage2
делает следующее.
- Внедряет службы для System.Net.Http.HttpClient и Microsoft.JSInterop.IJSRuntime.
- Включает тег
<img>
для отображения изображения. - Содержит метод C#
GetImageStreamAsync
для получения Stream изображения. Рабочее приложение может динамически создать изображение на основе конкретного пользователя или получить изображение из хранилища. В следующем примере извлекается аватар .NET для репозитория GitHubdotnet
. - Содержит метод
SetImageAsync
, который активируется при нажатии пользователем кнопки.SetImageAsync
выполняет следующие шаги:- Извлекает Stream из
GetImageStreamAsync
. - Заключает Stream в DotNetStreamReference, чтобы выполнить потоковую передачу изображения клиенту.
- Вызывает функцию JavaScript
setSource
, которая принимает данные на клиенте.
- Извлекает Stream из
Примечание.
Серверные приложения используют выделенную HttpClient службу для выполнения запросов, поэтому для регистрации Blazor службы не требуется никаких действий разработчиком серверного HttpClient приложения. Приложения на стороне клиента имеют регистрацию службы по умолчанию HttpClient при создании приложения из проектного шаблона Blazor.
HttpClient Если регистрация службы отсутствует в Program
файле клиентского приложения, добавьте ее, добавив builder.Services.AddHttpClient();
. Дополнительные сведения см. в статье Выполнение HTTP-запросов с помощью IHttpClientFactory в 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");
}
}
Следующий компонент ShowFile
загружает текстовый файл (files/quote.txt
) или PDF-файл (files/quote.pdf
) в элемент <iframe>
.
Предупреждение
<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 Blazor
- Отправка файлов: предварительная версия образа
- Скачивание файлов ASP.NET Core Blazor
- Вызов методов .NET из функций JavaScript в Blazor ASP.NET Core
- Вызов функций JavaScript из методов .NET в ASP.NET Core Blazor
-
Blazorпримеры репозитория GitHub (
dotnet/blazor-samples
как скачать)
ASP.NET Core