Eventos
Campeonato mundial de DataViz de Power BI
14 feb, 16 - 31 mar, 16
Con 4 posibilidades de entrar, podrías ganar un paquete de conferencia y convertirlo en el Live Grand Finale en Las Vegas
Saber másEste explorador ya no se admite.
Actualice a Microsoft Edge para aprovechar las características y actualizaciones de seguridad más recientes, y disponer de soporte técnico.
Nota
Esta no es la versión más reciente de este artículo. Para la versión actual, consulte la versión de .NET 9 de este artículo.
Advertencia
Esta versión de ASP.NET Core ya no se admite. Para obtener más información, consulte la directiva de compatibilidad de .NET y .NET Core. Para la versión actual, consulte la versión de .NET 9 de este artículo.
Importante
Esta información hace referencia a un producto en versión preliminar, el cual puede sufrir importantes modificaciones antes de que se publique la versión comercial. Microsoft no proporciona ninguna garantía, expresa o implícita, con respecto a la información proporcionada aquí.
Para la versión actual, consulte la versión de .NET 9 de este artículo.
En este artículo se explica cómo descargar archivos en aplicaciones Blazor.
Este artículo aborda los siguientes escenarios, en los que un explorador no debería abrir un archivo, sino descargarlo y guardarlo en el cliente:
Al descargar archivos de un origen diferente al de la aplicación, se aplican consideraciones de uso compartido de recursos entre orígenes (CORS). Para obtener más información, vea la sección Uso compartido de recursos entre orígenes (CORS).
Tenga precaución al proporcionar a los usuarios la capacidad de descargar archivos desde un servidor. Los ciberdelincuentes pueden ejecutar ataques de denegación de servicio (DoS), ataques de explotación de API o intentar poner en riesgo redes y servidores de otras maneras.
Estos son algunos de los pasos de seguridad con los que se reduce la probabilidad de sufrir ataques:
Esta sección se aplica a los archivos que normalmente tienen un tamaño de hasta 250 MB.
El enfoque recomendado para descargar archivos relativamente pequeños (< 250 MB) es transmitir contenido de archivo a un búfer de datos binarios sin procesar en el cliente con interoperabilidad de JavaScript (JS). Este enfoque es eficaz para los componentes que adoptan un modo de representación interactiva, pero no los componentes que adoptan la representación estática del lado servidor (SSR estático).
El enfoque recomendado para descargar archivos relativamente pequeños (< 250 MB) es transmitir contenido de archivo a un búfer de datos binarios sin procesar en el cliente con interoperabilidad de JavaScript (JS).
Advertencia
El enfoque de esta sección lee el contenido del archivo en un elemento JS ArrayBuffer
. Este enfoque carga todo el archivo en la memoria del cliente, lo que puede afectar al rendimiento. Para descargar archivos relativamente grandes (>= 250 MB), se recomienda seguir las instrucciones de la sección Descarga desde una dirección URL.
La siguiente función downloadFileFromStream
JS:
ArrayBuffer
.Blob
para ajustar ArrayBuffer
.HTMLAnchorElement
(elemento <a>
).fileName
) y la dirección URL (url
) para la descarga.click
en el elemento delimitador.url
) mediante una llamada a URL.revokeObjectURL
. Este es un paso importante para asegurarse de que no se pierde memoria en el cliente.<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>
Nota
Para obtener una guía general sobre la ubicación de JS y nuestras recomendaciones para aplicaciones de producción, consulta Ubicación de JavaScript en aplicaciones Blazor de ASP.NET Core.
El componente siguiente:
GetFileStream
para recuperar un elemento Stream para el archivo que se descarga en los clientes. Los enfoques alternativos incluyen recuperar un archivo del almacenamiento o generar un archivo dinámicamente en código de C#. Para esta demostración, la aplicación crea un archivo de 50 KB de datos aleatorios a partir de una nueva matriz de bytes (new byte[]
). Los bytes se encapsulan con una clase MemoryStream para que funcione como el archivo binario generado dinámicamente del ejemplo:DownloadFileFromStream
realiza las acciones siguientes: GetFileStream
.quote.txt
.downloadFileFromStream
JS para aceptar los datos en el cliente.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);
}
}
En el caso de un componente de una aplicación de lado servidor que debe devolver una Stream para un archivo físico, el componente puede llamar a File.OpenRead, como se muestra en el ejemplo siguiente:
private Stream GetFileStream() => File.OpenRead(@"{PATH}");
En el ejemplo anterior, el marcador de posición {PATH}
es la ruta de acceso al archivo. El prefijo @
indica que la cadena es un literal de cadena textual, que permite el uso de barras diagonales inversas (\
) en una ruta de acceso del sistema operativo Windows y comillas dobles incrustadas (""
) para un carácter de comillas simples en la ruta de acceso. Como alternativa, evita el literal de cadena (@
) y usa cualquiera de los enfoques siguientes:
\\
) y comillas (\"
)./
) en la ruta de acceso, que se admiten entre plataformas en aplicaciones ASP.NET Core y comillas de escape (\"
).Esta sección se aplica a los archivos que son relativamente grandes, normalmente de 250 MB o más.
El enfoque recomendado para descargar archivos relativamente grandes (>= 250 MB) con componentes o archivos representados interactivamente de cualquier tamaño para los componentes representados estáticamente es usar JS para desencadenar un elemento de anclaje con el nombre y la dirección URL del archivo.
El enfoque recomendado para descargar archivos relativamente grandes (>= 250 MB) es usar JS para desencadenar un elemento de anclaje con el nombre y la dirección URL del archivo.
En el ejemplo de esta sección se usa un archivo de descarga denominado quote.txt
, que se coloca en una carpeta denominada files
en la raíz web de la aplicación (carpeta wwwroot
). El uso de la carpeta files
es solo con fines de demostración. Puedes organizar los archivos descargables en cualquier disposición de carpetas dentro de la raíz web (carpeta wwwroot
) que prefieras, incluida la provisión de los archivos directamente desde la carpeta 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 siguiente función triggerFileDownload
JS:
HTMLAnchorElement
(elemento <a>
).fileName
) y la dirección URL (url
) para la descarga.click
en el elemento delimitador.<script>
window.triggerFileDownload = (fileName, url) => {
const anchorElement = document.createElement('a');
anchorElement.href = url;
anchorElement.download = fileName ?? '';
anchorElement.click();
anchorElement.remove();
}
</script>
Nota
Para obtener una guía general sobre la ubicación de JS y nuestras recomendaciones para aplicaciones de producción, consulta Ubicación de JavaScript en aplicaciones Blazor de ASP.NET Core.
En el siguiente componente de ejemplo se descarga el archivo desde el mismo origen que usa la aplicación. Si se intenta descargar el archivo desde un origen diferente, configura el uso compartido de recursos entre orígenes (CORS). Para obtener más información, vea la sección Uso compartido de recursos entre orígenes (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);
}
}
En el caso de los componentes interactivos, el botón del ejemplo anterior llama al controlador DownloadFileFromURL
para invocar la función JS de JavaScript (triggerFileDownload
).
Si el componente adopta la representación estática del lado servidor (SSR estático), agrega un controlador de eventos para el botón (addEventListener
(documentación de MDN)) para llamar triggerFileDownload
a las instrucciones de ASP.NET Core Blazor JavaScript con representación estática del lado servidor (SSR estático).
@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);
}
}
En el caso de los componentes interactivos, el botón del ejemplo anterior llama al controlador DownloadFileFromURL
para invocar la función JS de JavaScript (triggerFileDownload
).
Si el componente adopta la representación estática del lado servidor (SSR estático), agrega un controlador de eventos para el botón (addEventListener
(documentación de MDN)) para llamar triggerFileDownload
a las instrucciones de ASP.NET Core Blazor JavaScript con representación estática del lado servidor (SSR estático).
@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);
}
}
Cambia el puerto del ejemplo anterior para que coincida con el puerto de desarrollo localhost de tu entorno.
@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);
}
}
Cambia el puerto del ejemplo anterior para que coincida con el puerto de desarrollo localhost de tu entorno.
Si no se siguen los pasos necesarios para habilitar el uso compartido de recursos entre orígenes (CORS) para los archivos que no tienen el mismo origen que la aplicación, la descarga de archivos no pasará las comprobaciones de CORS realizadas por el explorador.
Para obtener más información sobre CORS con aplicaciones ASP.NET Core, y otros productos y servicios de Microsoft que hospedan archivos para su descarga, vea los siguientes recursos:
<a>
: elemento Anchor: Seguridad y privacidad (documentación de MDN)dotnet/blazor-samples
) (cómo descargar)Comentarios de ASP.NET Core
ASP.NET Core es un proyecto de código abierto. Seleccione un vínculo para proporcionar comentarios:
Eventos
Campeonato mundial de DataViz de Power BI
14 feb, 16 - 31 mar, 16
Con 4 posibilidades de entrar, podrías ganar un paquete de conferencia y convertirlo en el Live Grand Finale en Las Vegas
Saber másCursos
Módulo
Descargar y cargar archivos en una aplicación ASP.NET Core con Microsoft Graph - Training
Obtenga información sobre cómo hacer una lista, descargar y cargar los archivos de un usuario en una aplicación ASP.NET Core mediante Microsoft Graph.
Certificación
Microsoft Certified: Azure Developer Associate - Certifications
Cree soluciones de un extremo a otro en Microsoft Azure para crear Azure Functions, implementar y administrar aplicaciones web, desarrollar soluciones que usen Azure Storage, etc.