Exibir imagens e documentos no ASP.NET Core Blazor
Observação
Esta não é a versão mais recente deste artigo. Para informações sobre a versão vigente, confira a Versão do .NET 8 deste artigo.
Aviso
Esta versão do ASP.NET Core não tem mais suporte. Para obter mais informações, confira .NET e a Política de Suporte do .NET Core. Para informações sobre a versão vigente, confira a Versão do .NET 8 deste artigo.
Importante
Essas informações relacionam-se ao produto de pré-lançamento, que poderá ser substancialmente modificado antes do lançamento comercial. A Microsoft não oferece nenhuma garantia, explícita ou implícita, quanto às informações fornecidas aqui.
Para informações sobre a versão vigente, confira a Versão do .NET 8 deste artigo.
Este artigo descreve abordagens para exibir imagens e documentos em Blazor aplicativos.
Os exemplos neste artigo estão disponíveis para inspeção e uso nos Blazor aplicativos de exemplo:
dotnet/blazor-samples
Repositório GitHub: navegue até o aplicativo chamado BlazorSample_BlazorWebApp
(8.0 ou posterior), BlazorSample_Server
(7.0 ou anterior) ou BlazorSample_WebAssembly
.
Definir dinamicamente uma fonte de imagem
O exemplo a seguir demonstra como definir dinamicamente a origem de uma imagem com um campo C#.
O exemplo nesta seção usa três arquivos de imagem, chamados image1.png
, image2.png
e image3.png
. As imagens estão em uma pasta chamada images
na raiz web do aplicativo (wwwroot
). O uso da pasta images
é apenas para fins de demonstração. Você pode organizar ativos estáticos em qualquer estrutura de pastas que preferir, podendo até fornecê-los diretamente da wwwroot
pasta.
No seguinte componente ShowImage1
:
- A origem da imagem (
src
) é definida dinamicamente como o valor deimageSource
em C#. - O método
ShowImage
atualiza o campoimageSource
com base em um argumentoid
de imagem passado para o método . - Os botões renderizados chamam o método
ShowImage
com um argumento de imagem para cada uma das três imagens disponíveis na pastaimages
. O nome do arquivo é composto usando o argumento passado para o método e corresponde a uma das três imagens na pastaimages
.
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";
}
}
O exemplo anterior usa um campo C# para armazenar os dados de origem da imagem, mas você também pode usar uma propriedade C# para armazenar os dados.
Evite usar uma variável de loop diretamente em uma expressão lambda, como i
no exemplo de loop for
anterior. Caso contrário, a mesma variável será usada por todas as expressões lambda, o que resulta no uso do mesmo valor em todos os lambdas. Capture o valor da variável em uma variável local. No exemplo anterior:
- A variável de loop
i
é atribuída aimageId
. imageId
é usado na expressão lambda.
Como alternativa, use um loop foreach
com Enumerable.Range, que não tem o problema anterior:
@foreach (var imageId in Enumerable.Range(1, 3))
{
<button @onclick="() => ShowImage(imageId)">
Image @imageId
</button>
}
Para obter mais informações sobre expressões lambda com manipulação de eventos, consulte manipulação de eventos do ASP.NET Core Blazor.
Transmitir dados de imagem ou documento
Uma imagem ou outro tipo de documento, como um PDF, pode ser enviada diretamente ao cliente usando os recursos de interoperabilidade de streaming do Blazorem vez de hospedá-la em uma URL pública.
O exemplo nesta seção transmite dados de origem usando a interoperabilidade de JavaScript (JS). A seguinte função de setSource
JS:
- Pode ser usado para transmitir conteúdo para os seguintes elementos:
<body>
,<embed>
,<iframe>
,<img>
,<link>
,<object>
,<script>
,<style>
, e<track>
. - Aceita um elemento
id
para exibir o conteúdo do arquivo, um fluxo de dados para o documento, o tipo de conteúdo e um título para o elemento de exibição.
A função :
- Lê o fluxo fornecido em um
ArrayBuffer
. - Cria um
Blob
para encapsular oArrayBuffer
, definindo o tipo de conteúdo do blob. - Cria uma URL de objeto para servir como o endereço para o documento a ser mostrado.
- Define o título do elemento (
title
) a partir dotitle
parâmetro e define a origem do elemento (src
) a partir da URL do objeto criado. - Para evitar vazamentos de memória, a função chama
revokeObjectURL
para descartar a URL do objeto depois que o elemento carrega o recurso (load
event).
<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>
Observação
Para obter diretrizes gerais sobre o local JS e nossas recomendações para aplicativos de produção, consulte Localização do JavaScript em aplicativos ASP.NET Core Blazor.
O seguinte componente ShowImage2
:
- Injeta serviços para um System.Net.Http.HttpClient e Microsoft.JSInterop.IJSRuntime.
- Inclui uma tag
<img>
para exibir uma imagem. - Tem um método
GetImageStreamAsync
em C# para recuperar um Stream de uma imagem. Um aplicativo de produção pode gerar dinamicamente uma imagem com base no usuário específico ou recuperar uma imagem do armazenamento. O exemplo a seguir recupera o avatar do .NET para o repositóriodotnet
do GitHub. - Tem um método
SetImageAsync
que é disparado na seleção do botão pelo usuário.SetImageAsync
executa as seguintes ações:- Recupera o Stream de
GetImageStreamAsync
. - Encapsula o Stream em um DotNetStreamReference, que permite transmitir os dados da imagem para o cliente.
- Invoca a função JavaScript
setSource
, que aceita os dados no cliente.
- Recupera o Stream de
Observação
Os aplicativos do lado do servidor usam um serviço HttpClient dedicado para fazer solicitações, portanto, nenhuma ação é necessária pelo desenvolvedor de um aplicativo Blazor do lado do servidor para registrar um serviço HttpClient. Os aplicativos do lado do cliente têm um registro de serviço HttpClient padrão quando o aplicativo é criado a partir de um modelo de projeto Blazor. Se um registro de serviço HttpClient não estiver presente no arquivo Program
de um aplicativo do lado do cliente, forneça um regustri adicionando builder.Services.AddHttpClient();
. Para saber mais, confira Fazer solicitações HTTP usando IHttpClientFactory no 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");
}
}
O componente a seguir ShowFile
carrega um arquivo de texto (files/quote.txt
) ou um arquivo PDF (files/quote.pdf
) em um <iframe>
elemento (documentação MDN).
Cuidado
O uso do elemento <iframe>
no exemplo a seguir é seguro e não requer criação de área restrita porque o conteúdo é carregado do aplicativo, que é uma fonte confiável.
Ao carregar conteúdo de uma fonte não confiável ou entrada do usuário, um elemento implementado <iframe>
incorretamente corre o risco de criar vulnerabilidades de segurança.
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);
}
}
Recursos adicionais
- Uploads de arquivo Blazor do ASP.NET Core
- Uploads de arquivo: Pré-visualização de imagem de upload
- Downloads de arquivo Blazor no ASP.NET Core
- Chamar métodos .NET de funções JavaScript no ASP.NET Core Blazor
- Chamar funções JavaScript de métodos .NET no ASP.NET Core Blazor
- Blazor amostras do repositório GitHub (
dotnet/blazor-samples
) (como baixar)