Téléchargements de fichiers ASP.NET Core Blazor
Note
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 explique comment télécharger des fichiers dans Blazor applications.
Téléchargements de fichiers
Cet article couvre des approches pour les scénarios suivants, où un fichier ne doit pas être ouvert par un navigateur, mais téléchargé et enregistré sur le client :
- Diffuser en streaming du contenu de fichier dans une mémoire tampon de données binaires brutes sur le client : en général, cette approche est utilisée pour les fichiers relativement petits (< 250 Mo).
- Télécharger un fichier par le biais d’une URL sans diffusion en streaming : en général, cette approche est utilisée pour les fichiers relativement volumineux (> 250 Mo).
Lors du téléchargement de fichiers à partir d’une origine différente de celle de l’application, les considérations de partage des ressources cross-origin (CORS, Cross-Origin Resource Sharing) s’appliquent. Pour plus d’informations, consultez la section Partage des ressources cross-origin (CORS, Cross-Origin Resource Sharing).
Considérations relatives à la sécurité
Soyez prudent lorsque vous fournissez aux utilisateurs la possibilité de télécharger des fichiers à partir d’un serveur. Les cyberattaquants peuvent effectuer des attaques par déni de service (DoS) ou des attaques d’exploitation d’API, ou tenter de compromettre des réseaux et des serveurs en utilisant d’autres moyens.
Les étapes de sécurité qui réduisent la probabilité d’une attaque réussie sont les suivantes :
- Téléchargez des fichiers à partir d’une zone de téléchargement de fichier dédiée sur le serveur, de préférence à partir d’un lecteur non système. L’utilisation d’un emplacement dédié facilite la prise de restrictions de sécurité sur les fichiers téléchargeables. Désactivez les autorisations d’exécution sur la zone de téléchargement de fichier.
- Les contrôles de sécurité côté client sont faciles à contourner par des utilisateurs malveillants. De plus, effectuez toujours des vérifications de sécurité côté client sur le serveur.
- Ne recevez pas d’utilisateurs ou d’autres sources non approuvées des fichiers que vous rendez ensuite disponibles en téléchargement immédiat sans effectuer de vérifications de sécurité sur ces fichiers. Pour plus d’informations, consultez Charger des fichiers dans ASP.NET Core.
Télécharger à partir d’un flux
Cette section s’applique aux fichiers dont la taille maximale est généralement de 250 Mo.
L’approche recommandée pour télécharger des fichiers relativement petits (< 250 Mo) consiste à diffuser en streaming du contenu de fichier dans une mémoire tampon de données binaires brutes sur le client avec l’interopérabilité JavaScript (JS). Cette approche est efficace pour les composants qui adoptent un mode de rendu interactif, mais pas pour les composants qui adoptent le rendu statique côté serveur (SSR statique).
L’approche recommandée pour télécharger des fichiers relativement petits (< 250 Mo) consiste à diffuser en streaming du contenu de fichier dans une mémoire tampon de données binaires brutes sur le client avec l’interopérabilité JavaScript (JS).
Avertissement
L’approche décrite dans cette section lit le contenu du fichier dans un JS ArrayBuffer
. Cette approche charge l’ensemble du fichier dans la mémoire du client, ce qui peut nuire aux performances. Pour télécharger des fichiers relativement volumineux (>= 250 Mo), nous vous recommandons de suivre les instructions fournies dans la section Télécharger à partir d’une URL.
La fonction downloadFileFromStream
JS suivante :
- Lit le flux fourni dans un
ArrayBuffer
. - Crée un
Blob
pour encapsuler leArrayBuffer
. - Crée une URL d’objet pour servir d’adresse de téléchargement du fichier.
- Crée un
HTMLAnchorElement
(<a>
élement). - Attribue le nom (
fileName
) et l’URL (url
) du fichier pour le téléchargement. - Déclenche le téléchargement en activant un événement
click
sur l’élément d’ancrage. - Supprime l’élément d’ancrage.
- Révoque l’URL d’objet (
url
) en appelantURL.revokeObjectURL
. Il s’agit d’une étape importante pour garantir qu’il n’y a pas de fuite de mémoire sur le client.
<script>
window.downloadFileFromStream = async (fileName, contentStreamReference) => {
const arrayBuffer = await contentStreamReference.arrayBuffer();
const blob = new Blob([arrayBuffer]);
const url = URL.createObjectURL(blob);
const anchorElement = document.createElement('a');
anchorElement.href = url;
anchorElement.download = fileName ?? '';
anchorElement.click();
anchorElement.remove();
URL.revokeObjectURL(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 suivant :
- Utilise l’interopérabilité de streaming d’octets native pour garantir un transfert efficace du fichier vers le client.
- A une méthode nommée
GetFileStream
pour récupérer un Stream pour le fichier qui est téléchargé sur les clients. D’autres approches permettent de récupérer un fichier à partir du stockage ou de générer de façon dynamique un fichier dans du code C#. Pour cette démonstration, l’application crée un fichier de données aléatoires de 50 Ko à partir d’un nouveau tableau d’octets (new byte[]
). Les octets sont wrappés avec un MemoryStream pour servir de fichier binaire généré dynamiquement de l’exemple. - La méthode
DownloadFileFromStream
:- Récupère le Stream partir de
GetFileStream
. - Spécifie un nom de fichier lorsque le fichier est enregistré sur la machine de l’utilisateur. L’exemple suivant nomme le fichier
quote.txt
. - Envelopper le Stream dans un DotNetStreamReference, ce qui permet de diffuser en streaming les données du fichier vers le client.
- Appelle la fonction JS
downloadFileFromStream
pour accepter les données sur le client.
- Récupère le Stream partir de
FileDownload1.razor
:
@page "/file-download-1"
@using System.IO
@inject IJSRuntime JS
<PageTitle>File Download 1</PageTitle>
<h1>File Download Example 1</h1>
<button @onclick="DownloadFileFromStream">
Download File From Stream
</button>
@code {
private Stream GetFileStream()
{
var randomBinaryData = new byte[50 * 1024];
var fileStream = new MemoryStream(randomBinaryData);
return fileStream;
}
private async Task DownloadFileFromStream()
{
var fileStream = GetFileStream();
var fileName = "log.bin";
using var streamRef = new DotNetStreamReference(stream: fileStream);
await JS.InvokeVoidAsync("downloadFileFromStream", fileName, streamRef);
}
}
@page "/file-download-1"
@using System.IO
@inject IJSRuntime JS
<PageTitle>File Download 1</PageTitle>
<h1>File Download Example 1</h1>
<button @onclick="DownloadFileFromStream">
Download File From Stream
</button>
@code {
private Stream GetFileStream()
{
var randomBinaryData = new byte[50 * 1024];
var fileStream = new MemoryStream(randomBinaryData);
return fileStream;
}
private async Task DownloadFileFromStream()
{
var fileStream = GetFileStream();
var fileName = "log.bin";
using var streamRef = new DotNetStreamReference(stream: fileStream);
await JS.InvokeVoidAsync("downloadFileFromStream", fileName, streamRef);
}
}
@page "/file-download-1"
@using System.IO
@inject IJSRuntime JS
<h1>File Download Example</h1>
<button @onclick="DownloadFileFromStream">
Download File From Stream
</button>
@code {
private Stream GetFileStream()
{
var randomBinaryData = new byte[50 * 1024];
var fileStream = new MemoryStream(randomBinaryData);
return fileStream;
}
private async Task DownloadFileFromStream()
{
var fileStream = GetFileStream();
var fileName = "log.bin";
using var streamRef = new DotNetStreamReference(stream: fileStream);
await JS.InvokeVoidAsync("downloadFileFromStream", fileName, streamRef);
}
}
@page "/file-download-1"
@using System.IO
@inject IJSRuntime JS
<h1>File Download Example</h1>
<button @onclick="DownloadFileFromStream">
Download File From Stream
</button>
@code {
private Stream GetFileStream()
{
var randomBinaryData = new byte[50 * 1024];
var fileStream = new MemoryStream(randomBinaryData);
return fileStream;
}
private async Task DownloadFileFromStream()
{
var fileStream = GetFileStream();
var fileName = "log.bin";
using var streamRef = new DotNetStreamReference(stream: fileStream);
await JS.InvokeVoidAsync("downloadFileFromStream", fileName, streamRef);
}
}
Pour un composant d’une application d’un côté serveur qui doit retourner un Stream pour un fichier physique, le composant peut appeler File.OpenRead, comme le montre l’exemple suivant :
private Stream GetFileStream() => File.OpenRead(@"{PATH}");
Dans l’exemple précédent, l’espace réservé {PATH}
est le chemin du fichier. Le préfixe @
indique que la chaîne est un littéral de chaîne verbatim, ce qui permet d’utiliser des barres obliques inverses (\
) dans un chemin du système d’exploitation Windows et des guillemets doubles incorporés (""
) pour un guillemet simple dans le chemin. Vous pouvez également éviter le littéral de chaîne (@
) et utiliser l’une des approches suivantes :
- Utilisez des barres obliques inverses dans une séquence d’échappement (
\\
) et des guillemets (\"
) dans une séquence d’échappement. - Utilisez des barres obliques (
/
) dans le chemin : elles sont prises en charge sur toutes les plateformes dans les applications ASP.NET Core, et des guillemets dans une séquence d’échappement (\"
).
Télécharger à partir d’une URL
Cette section s’applique aux fichiers relativement volumineux, d’une taille généralement supérieure ou égale à 250 Mo.
L’approche recommandée pour le téléchargement de fichiers relativement volumineux (> = 250 Mo) avec des composants ou des fichiers rendus de manière interactive de toute taille pour des composants rendus de manière statique consiste à utiliser JS pour déclencher un élément d’ancrage avec le nom et l’URL du fichier.
L’approche recommandée pour le téléchargement de fichiers relativement volumineux (> = 250 Mo) consiste à utiliser JS pour déclencher un élément d’ancrage avec le nom et l’URL du fichier.
L’exemple de cette section utilise un fichier de téléchargement nommé quote.txt
, qui est placé dans un dossier nommé files
à la racine web de l’application (dossier wwwroot
). Le dossier files
est utilisé uniquement à des fins de démonstration. Vous pouvez organiser les fichiers téléchargeables dans n’importe quelle disposition de dossier au sein de la racine web (dossier wwwroot
) de votre choix, ce qui inclut de traiter les fichiers directement à partir du dossier wwwroot
.
wwwroot/files/quote.txt
:
When victory is ours, we'll wipe every trace of the Thals and their city from the face of this land. We will avenge the deaths of all Kaleds who've fallen in the cause of right and justice and build a peace which will be a monument to their sacrifice. Our battle cry will be "Total extermination of the Thals!"
- General Ravon (Guy Siner, http://guysiner.com/)
Dr. Who: Genesis of the Daleks (https://www.bbc.co.uk/programmes/p00vd5g2)
Copyright 1975 BBC (https://www.bbc.co.uk/)
When victory is ours, we'll wipe every trace of the Thals and their city from the face of this land. We will avenge the deaths of all Kaleds who've fallen in the cause of right and justice and build a peace which will be a monument to their sacrifice. Our battle cry will be "Total extermination of the Thals!"
- General Ravon (Guy Siner, http://guysiner.com/)
Dr. Who: Genesis of the Daleks (https://www.bbc.co.uk/programmes/p00vd5g2)
Copyright 1975 BBC (https://www.bbc.co.uk/)
When victory is ours, we'll wipe every trace of the Thals and their city from the face of this land. We will avenge the deaths of all Kaleds who've fallen in the cause of right and justice and build a peace which will be a monument to their sacrifice. Our battle cry will be "Total extermination of the Thals!"
- General Ravon (Guy Siner, http://guysiner.com/)
Dr. Who: Genesis of the Daleks (https://www.bbc.co.uk/programmes/p00vd5g2)
Copyright 1975 BBC (https://www.bbc.co.uk/)
When victory is ours, we'll wipe every trace of the Thals and their city from the face of this land. We will avenge the deaths of all Kaleds who've fallen in the cause of right and justice and build a peace which will be a monument to their sacrifice. Our battle cry will be "Total extermination of the Thals!"
- General Ravon (Guy Siner, http://guysiner.com/)
Dr. Who: Genesis of the Daleks (https://www.bbc.co.uk/programmes/p00vd5g2)
Copyright 1975 BBC (https://www.bbc.co.uk/)
La fonction triggerFileDownload
JS suivante :
- Crée un
HTMLAnchorElement
(<a>
élement). - Attribue le nom (
fileName
) et l’URL (url
) du fichier pour le téléchargement. - Déclenche le téléchargement en activant un événement
click
sur l’élément d’ancrage. - Supprime l’élément d’ancrage.
<script>
window.triggerFileDownload = (fileName, url) => {
const anchorElement = document.createElement('a');
anchorElement.href = url;
anchorElement.download = fileName ?? '';
anchorElement.click();
anchorElement.remove();
}
</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.
L’exemple de composant suivant télécharge le fichier à partir de la même origine que celle utilisée par l’application. Si le téléchargement de fichier est tenté à partir d’une autre origine, configurez le partage des ressources cross-origin (CORS, Cross-Origin Resource Sharing). Pour plus d’informations, consultez la section Partage des ressources cross-origin (CORS).
FileDownload2.razor
:
@page "/file-download-2"
@inject IJSRuntime JS
<PageTitle>File Download 2</PageTitle>
<h1>File Download Example 2</h1>
<button @onclick="DownloadFileFromURL">
Download File From URL
</button>
@code {
private async Task DownloadFileFromURL()
{
var fileName = "quote.txt";
var fileURL = "/files/quote.txt";
await JS.InvokeVoidAsync("triggerFileDownload", fileName, fileURL);
}
}
Pour les composants interactifs, le bouton de l’exemple précédent appelle le gestionnaire DownloadFileFromURL
pour appeler la fonction JavaScript triggerFileDownload
(JS).
Si le composant adopte le rendu statique côté serveur (SSR statique), ajoutez un gestionnaire d’événements pour le bouton (addEventListener
(documentation MDN)) pour appeler triggerFileDownload
en suivant les instructions de JavaScript Blazor ASP.NET Core avec rendu statique côté serveur (SSR statique).
@page "/file-download-2"
@inject IJSRuntime JS
<PageTitle>File Download 2</PageTitle>
<h1>File Download Example 2</h1>
<button @onclick="DownloadFileFromURL">
Download File From URL
</button>
@code {
private async Task DownloadFileFromURL()
{
var fileName = "quote.txt";
var fileURL = "/files/quote.txt";
await JS.InvokeVoidAsync("triggerFileDownload", fileName, fileURL);
}
}
Pour les composants interactifs, le bouton de l’exemple précédent appelle le gestionnaire DownloadFileFromURL
pour appeler la fonction JavaScript triggerFileDownload
(JS).
Si le composant adopte le rendu statique côté serveur (SSR statique), ajoutez un gestionnaire d’événements pour le bouton (addEventListener
(documentation MDN)) pour appeler triggerFileDownload
en suivant les instructions de JavaScript Blazor ASP.NET Core avec rendu statique côté serveur (SSR statique).
@page "/file-download-2"
@inject IJSRuntime JS
<h1>File Download Example 2</h1>
<button @onclick="DownloadFileFromURL">
Download File From URL
</button>
@code {
private async Task DownloadFileFromURL()
{
var fileName = "quote.txt";
var fileURL = "https://localhost:5001/files/quote.txt";
await JS.InvokeVoidAsync("triggerFileDownload", fileName, fileURL);
}
}
Modifiez le port dans l’exemple précédent pour qu’il corresponde au port de développement localhost de votre environnement.
@page "/file-download-2"
@inject IJSRuntime JS
<h1>File Download Example 2</h1>
<button @onclick="DownloadFileFromURL">
Download File From URL
</button>
@code {
private async Task DownloadFileFromURL()
{
var fileName = "quote.txt";
var fileURL = "https://localhost:5001/files/quote.txt";
await JS.InvokeVoidAsync("triggerFileDownload", fileName, fileURL);
}
}
Modifiez le port dans l’exemple précédent pour qu’il corresponde au port de développement localhost de votre environnement.
CORS (Cross Origin Resource Sharing)
Si vous n’effectuez pas d’étapes supplémentaires pour activer le partage de ressources cross-origin (CORS) pour les fichiers qui n’ont pas la même origine que l’application, le téléchargement de fichiers ne réussira pas les vérifications CORS effectuées par le navigateur.
Pour plus d’informations sur le partage CORS avec des applications ASP.NET Core et d’autres produits et services Microsoft qui hébergent des fichiers à télécharger, consultez les ressources suivantes :
- Activation des demandes multi-origines (CORS) dans ASP.NET Core
- Utilisation d’Azure CDN avec CORS (documentation Azure)
- Prise en charge du service Partage des ressources cross-origine (CORS) pour le Stockage Azure (documentation REST)
- Services cloud principaux - Configurer CORS pour votre site web et vos ressources de stockage (module Learn)
- Informations de référence sur la configuration du module IIS CORS (documentation IIS)
Ressources supplémentaires
- Fichiers statiques Blazor ASP.NET Core
- Interopérabilité JavaScript ASP.NET Core Blazor (interopérabilité JS)
- Emplacement du JavaScript dans les applications ASP.NET CoreBlazor
- JavaScript ASP.NET CoreBlazor avec rendu côté serveur statique (SSR statique)
<a>
: l’élément d’ancrage - Sécurité et privacy (documentation MDN)- Chargements de fichiers Blazor ASP.NET Core
- Blazor exemples du référentiel GitHub (
dotnet/blazor-samples
) (procédure de téléchargement)