Afficher des images et des documents dans Blazor ASP.NET Core
Remarque
Ceci n’est pas la dernière version de cet article. Pour la version actuelle, consultez la version .NET 8 de cet article.
Avertissement
Cette version d’ASP.NET Core n’est plus prise en charge. Pour plus d’informations, consultez la Stratégie de prise en charge de .NET et .NET Core. Pour la version actuelle, consultez la version .NET 8 de cet article.
Important
Ces informations portent sur la préversion du produit, qui est susceptible d’être en grande partie modifié avant sa commercialisation. Microsoft n’offre aucune garantie, expresse ou implicite, concernant les informations fournies ici.
Pour la version actuelle, consultez la version .NET 8 de cet article.
Cet article décrit les approches d’affichage d’images et de documents dans les applications Blazor.
Les exemples de cet article sont disponibles pour l’inspection et l’utilisation dans les exemples d’applications Blazor :
Référentiel GitHub dotnet/blazor-samples
: accédez à l’application nommée BlazorSample_BlazorWebApp
(8.0 ou version ultérieure), BlazorSample_Server
(7.0 ou version antérieure) ou BlazorSample_WebAssembly
.
Définition dynamique d’une source d’image
L’exemple suivant montre comment définir dynamiquement la source d’une image avec un champ C#.
L’exemple de cette section utilise trois fichiers image, nommés image1.png
, image2.png
et image3.png
. Placez les images dans un nouveau dossier nommé images
à la racine web de l’application (wwwroot
). Le dossier images
est utilisé uniquement à des fins de démonstration. Vous pouvez organiser les actifs statiques dans n’importe quelle disposition de dossier de votre choix et servir les actifs directement à partir du dossier wwwroot
.
Dans le composant ShowImage1
suivant :
- La source de l’image (
src
) est définie dynamiquement sur la valeur deimageSource
en C#. - La méthode
ShowImage
met à jour le champimageSource
en fonction d’un argument d’imageid
passé à la méthode. - Les boutons de rendu appellent la méthode
ShowImage
avec un argument image pour chacune des trois images disponibles dans le dossierimages
. Le nom de fichier est composé à l’aide de l’argument passé à la méthode et correspond à l’une des trois images du dossierimages
.
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";
}
}
L’exemple précédent utilise un champ C# pour contenir les données sources de l’image, mais vous pouvez également utiliser une propriété C# pour contenir les données.
Évitez d’utiliser une variable de boucle directement dans une expression lambda, comme i
dans l’exemple de boucle for
précédent. Sinon, la même variable est utilisée par toutes les expressions lambda, ce qui entraîne l’utilisation de la même valeur dans toutes les expressions lambda. Capturez la valeur de la variable dans une variable locale. Dans l'exemple précédent :
- La variable de boucle
i
est affectée àimageId
. imageId
est utilisé dans l’expression lambda.
Vous pouvez également utiliser une boucle foreach
avec Enumerable.Range, qui ne souffre pas du problème précédent :
@foreach (var imageId in Enumerable.Range(1, 3))
{
<button @onclick="() => ShowImage(imageId)">
Image @imageId
</button>
}
Pour plus d’informations sur les expressions lambda avec gestion des événements, consultez Gestion des événements Blazor ASP.NET Core.
Diffuser en continu des données d’image ou de document
Une image ou un autre type de document, comme un PDF, peuvent être envoyés directement au client à l’aide des fonctions d’interopérabilité de diffusion en continu de Blazor au lieu d’héberger l’image sur une URL publique.
L’exemple de cette section diffuse en continu des données sources à l’aide de l’interopérabilité JavaScript (JS). La fonction setSource
JS suivante :
- Peut être utilisé pour diffuser en continu du contenu pour les éléments suivants :
<body>
,<embed>
,<iframe>
,<img>
,<link>
,<object>
,<script>
,<style>
et<track>
. - Accepte un élément
id
pour afficher le contenu du fichier, un flux de données pour le document, le type de contenu et un titre pour l’élément d’affichage.
La fonction :
- Lit le flux fourni dans un
ArrayBuffer
. - Crée un
Blob
pour envelopper leArrayBuffer
, en définissant le type de contenu du blob. - Crée une URL d’objet pour servir d’adresse au document à afficher.
- Définissez le titre de l’élément (
title
) à partir dutitle
paramètre et définit la source de l’élément (src
) à partir de l’URL de l’objet créé. - Pour éviter les fuites de mémoire, la fonction appelle
revokeObjectURL
à supprimer l’URL de l’objet une fois que l’élément charge la ressource (événementload
).
<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>
Remarque
Pour obtenir une aide générale sur l’emplacement deJS et nos recommandations pour les applications de production, consultez Emplacement de JavaScript dans les applications Blazor ASP.NET Core.
Le composant ShowImage2
suivant :
- Injecte des services pour un System.Net.Http.HttpClient et Microsoft.JSInterop.IJSRuntime.
- Inclut une balise
<img>
pour afficher une image. - Dispose d’une méthode C#
GetImageStreamAsync
pour récupérer un Stream pour une image. Une application de production peut générer dynamiquement une image en fonction de l’utilisateur spécifique ou récupérer une image à partir du stockage. L’exemple suivant récupère l’avatar .NET pour le dépôt GitHubdotnet
. - Dispose d’une méthode
SetImageAsync
qui est déclenchée lors de la sélection du bouton par l’utilisateur.SetImageAsync
effectue les tâches suivantes :- Récupère le Stream partir de
GetImageStreamAsync
. - Encapsule le Stream dans un DotNetStreamReference, ce qui permet de diffuser en continu les données d’image vers le client.
- Appelle la fonction JavaScript
setSource
, qui accepte les données sur le client.
- Récupère le Stream partir de
Remarque
Les applications côté serveur utilisent un service HttpClient dédié pour effectuer des requêtes. Par conséquent, aucune action n’est requise par le développeur d’une application Blazor côté serveur pour inscrire un service HttpClient. Les applications côté client ont une inscription de service HttpClient par défaut lorsque l’application est créée à partir d’un modèle de projet Blazor. Si aucune inscription de service HttpClient n’est présente dans le fichier Program
d’une application côté client, fournissez-en une en ajoutant builder.Services.AddHttpClient();
. Pour plus d’informations, consultez Effectuer des requêtes HTTP en utilisant IHttpClientFactory dans 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");
}
}
Le composant ShowFile
suivant charge un fichier texte (files/quote.txt
) ou un fichier PDF (files/quote.pdf
) dans un élément <iframe>
(documentation MDN).
Attention
L’utilisation de l’élément <iframe>
dans l’exemple suivant est sécurisée et ne nécessite pas d’utiliser un sandbox, car le contenu est chargé à partir de l’application, qui est une source approuvée.
Lors du chargement de contenu à partir d’une source ou d’une entrée utilisateur non approuvée, un élément <iframe>
mal implémenté risque de créer des vulnérabilités de sécurité.
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
<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);
}
}
Ressources supplémentaires
- Chargements de fichiers Blazor ASP.NET Core
- Chargements de fichiers : Charger un aperçu des images
- Téléchargements de fichiers dans ASP.NET Core Blazor
- Appeler des méthodes .NET à partir de fonctions JavaScript dans ASP.NET Core Blazor
- Appeler des fonctions JavaScript à partir de méthodes .NET dans ASP.NET Core Blazor
- Dépôt GitHub d’exemples Blazor (
dotnet/blazor-samples
) (Comment télécharger)