Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Observação
Esta não é a versão mais recente deste artigo. Para a versão atual, consulte a versão .NET 10 deste artigo.
Advertência
Esta versão do ASP.NET Core não é mais suportada. Para obter mais informações, consulte a Política de suporte do .NET e .NET Core. Para a versão atual, consulte a versão .NET 10 deste artigo.
Este artigo explica como baixar arquivos em Blazor aplicativos.
Downloads de arquivos
Este artigo aborda abordagens para os seguintes cenários, onde um arquivo não deve ser aberto por um navegador, mas baixado e salvo no cliente:
- Transmitir o conteúdo do arquivo para um buffer de dados binários brutos no cliente: Normalmente, essa abordagem é usada para arquivos relativamente pequenos (< 250 MB).
- Descarregar um ficheiro através de um URL sem streaming: Normalmente, esta abordagem é utilizada para ficheiros relativamente grandes (> 250 MB).
Ao baixar arquivos de uma origem diferente do aplicativo, aplicam-se as considerações de Compartilhamento de Recursos entre Origens (CORS). Para obter mais informações, consulte a seção Cross-Origin Resource Sharing (CORS).
Considerações de segurança
Tenha cuidado ao fornecer aos usuários a capacidade de baixar arquivos de um servidor. Os ciberatacantes podem executar ataques de negação de serviço (DoS), ataques de exploração de API ou tentar comprometer redes e servidores de outras formas.
As etapas de segurança que reduzem a probabilidade de um ataque bem-sucedido são:
- Transfira ficheiros a partir de uma área dedicada de transferência de ficheiros no servidor, de preferência a partir de uma unidade que não seja do sistema. A utilização de uma localização dedicada facilita a imposição de restrições de segurança aos ficheiros transferíveis. Desative as permissões de execução na área de download de arquivos.
- As verificações de segurança do lado do cliente são fáceis de contornar por usuários mal-intencionados. Sempre execute verificações de segurança do lado do cliente no servidor também.
- Não receba ficheiros de utilizadores ou de outras fontes não fidedignas e, em seguida, disponibilize os ficheiros para transferência imediata sem executar verificações de segurança nos ficheiros. Para obter mais informações, consulte Carregar arquivos no ASP.NET Core.
Download de um fluxo
Esta seção se aplica a arquivos que normalmente têm até 250 MB de tamanho.
A abordagem recomendada para baixar arquivos relativamente pequenos (<250 MB) é transmitir o conteúdo do arquivo para um buffer de dados binários brutos no cliente com interoperabilidade JavaScript (JS). Essa abordagem é eficaz para componentes que adotam um modo de renderização interativo, mas não para componentes que adotam renderização estática do lado do servidor (SSR estático).
A abordagem recomendada para baixar arquivos relativamente pequenos (<250 MB) é transmitir o conteúdo do arquivo para um buffer de dados binários brutos no cliente com interoperabilidade JavaScript (JS).
Advertência
A abordagem nesta seção lê o conteúdo do arquivo para um JS ArrayBuffer. Essa abordagem carrega o arquivo inteiro na memória do cliente, o que pode prejudicar o desempenho. Para transferir ficheiros relativamente grandes (>= 250 MB), recomendamos que siga as orientações na secção Transferir a partir de um URL .
A seguinte função downloadFileFromStreamJS:
- Lê o fluxo fornecido em um
ArrayBuffer. - Cria um
Blobpara envolver oArrayBuffer. - Cria uma URL de objeto para servir como endereço de download do arquivo.
- Cria um
HTMLAnchorElementelemento (<a>). - Atribui o nome (
fileName) e o URL (url) do arquivo para download. - Aciona o download disparando um
clickevento no elemento âncora. - Remova o elemento âncora.
- Revoga a URL do objeto (
url) chamandoURL.revokeObjectURL. Esta é uma etapa importante para garantir que a memória não seja vazada no 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>
Observação
Para obter orientações gerais sobre a JS localização e as nossas recomendações para aplicações de produção, consulte a localização de JavaScript em aplicações ASP.NET Core Blazor.
O seguinte componente:
- Usa interoperabilidade nativa de streaming de bytes para garantir a transferência eficiente do arquivo para o cliente.
- Tem um método nomeado
GetFileStreampara recuperar um Stream para o ficheiro que é baixado para os clientes. Abordagens alternativas incluem recuperar um arquivo do armazenamento ou gerar um arquivo dinamicamente em código C#. Para esta demonstração, o aplicativo cria um arquivo de 50 KB de dados aleatórios de uma nova matriz de bytes (new byte[]). Os bytes são encapsulados com a MemoryStream para servir como o arquivo binário gerado dinamicamente do exemplo. - O
DownloadFileFromStreammétodo:- Recupera o Stream de
GetFileStream. - Especifica um nome de arquivo quando o arquivo é salvo na máquina do usuário. O exemplo a seguir nomeia o arquivo
quote.txt. - Encapsula o Stream em um DotNetStreamReference, que permite transmitir os dados do arquivo para o cliente.
- Invoca a
downloadFileFromStreamJS função para aceitar os dados no cliente.
- Recupera o Stream 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);
}
}
Para um componente em um aplicativo do lado do servidor que deve retornar um Stream para um arquivo físico, o componente pode chamar File.OpenRead, como demonstra o exemplo a seguir:
private Stream GetFileStream() => File.OpenRead(@"{PATH}");
No exemplo anterior, o espaço reservado {PATH} é o caminho para o arquivo. O prefixo @ indica que a cadeia de caracteres é um literal de cadeia de caracteres verbatim, que permite o uso de barras invertidas (\) num caminho do sistema operativo Windows e aspas duplas incorporadas ("") para uma aspa simples no caminho. Como alternativa, evite a cadeia de caracteres literal (@) e use uma das seguintes abordagens:
- Use barras invertidas com escape (
\\) e aspas (\"). - Use barras (
/) no caminho, que são suportadas entre plataformas em aplicativos ASP.NET Core, e aspas com escape (\").
Transferir a partir de um URL
Esta secção aplica-se a ficheiros relativamente grandes, normalmente com 250 MB ou mais.
A abordagem recomendada para baixar arquivos relativamente grandes (>= 250 MB) com componentes renderizados interativamente ou arquivos de qualquer tamanho para componentes renderizados estaticamente é usar JS para acionar um elemento âncora com o nome e a URL do arquivo.
A abordagem recomendada para baixar arquivos relativamente grandes (>= 250 MB) é usar JS para acionar um elemento âncora com o nome e a URL do arquivo.
O exemplo nesta seção usa um arquivo de download chamado quote.txt, que é colocado em uma pasta nomeada files na raiz da Web do aplicativo (wwwroot pasta). O uso da pasta files é apenas para fins de demonstração. Você pode organizar ficheiros para download em qualquer layout de pasta dentro do diretório raiz da web (wwwroot pasta) que preferir, inclusive servindo os ficheiros diretamente da wwwroot pasta.
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/)
A seguinte função triggerFileDownloadJS:
- Cria um
HTMLAnchorElementelemento (<a>). - Atribui o nome (
fileName) e o URL (url) do arquivo para download. - Aciona o download disparando um
clickevento no elemento âncora. - Remova o elemento âncora.
<script>
window.triggerFileDownload = (fileName, url) => {
const anchorElement = document.createElement('a');
anchorElement.href = url;
anchorElement.download = fileName ?? '';
anchorElement.click();
anchorElement.remove();
}
</script>
Observação
Para obter orientações gerais sobre a JS localização e as nossas recomendações para aplicações de produção, consulte a localização de JavaScript em aplicações ASP.NET Core Blazor.
O componente de exemplo a seguir baixa o arquivo da mesma origem que o aplicativo usa. Se o download do arquivo for tentado de uma origem diferente, configure o CORS (Cross-Origin Resource Sharing). Para obter mais informações, consulte a seção Cross-Origin Resource Sharing (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);
}
}
Para componentes interativos, o botão no exemplo anterior chama o manipulador DownloadFileFromURL para invocar a função JavaScript JS (triggerFileDownload).
Se o componente adotar renderização estática do lado do servidor (SSR estático), adicione um manipulador de eventos para o botão (addEventListener) a ser chamado triggerFileDownload seguindo as orientações do ASP.NET Core Blazor JavaScript com renderização estática do lado do 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);
}
}
Para componentes interativos, o botão no exemplo anterior chama o manipulador DownloadFileFromURL para invocar a função JavaScript JS (triggerFileDownload).
Se o componente adotar renderização estática do lado do servidor (SSR estático), adicione um manipulador de eventos para o botão (addEventListener) a ser chamado triggerFileDownload seguindo as orientações do ASP.NET Core Blazor JavaScript com renderização estática do lado do 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);
}
}
Altere a porta no exemplo anterior para corresponder à porta de desenvolvimento localhost do seu ambiente.
@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);
}
}
Altere a porta no exemplo anterior para corresponder à porta de desenvolvimento localhost do seu ambiente.
Compartilhamento de recursos entre origens (CORS)
Sem tomar medidas adicionais para habilitar o CORS (Cross-Origin Resource Sharing) para arquivos que não têm a mesma origem do aplicativo, o download de arquivos não passará pelas verificações CORS feitas pelo navegador.
Para obter mais informações sobre o CORS com aplicativos ASP.NET Core e outros produtos e serviços da Microsoft que hospedam arquivos para download, consulte os seguintes recursos:
- Habilitar solicitações entre origens (CORS) no ASP.NET Core
- Usando a CDN do Azure com CORS (documentação do Azure)
- Suporte a CORS (Cross-Origin Resource Sharing) para o Armazenamento do Azure (REST documentação)
- Core Cloud Services - Configure o CORS para o seu website e ativos de armazenamento (módulo Aprender)
- Referência de configuração do módulo CORS do IIS (documentação do IIS)
Recursos adicionais
- ASP.NET Core Blazor Arquivos Estáticos
- Interoperabilidade JavaScript no ASP.NET Core Blazor (JS interoperabilidade)
- Localização do JavaScript nas aplicações ASP.NET Core Blazor
- ASP.NET Core Blazor JavaScript com renderização estática do lado do servidor (SSR estático)
-
<a>: O elemento Anchor: Segurança e privacidade (documentação MDN) - ASP.NET Core Blazor carregamento de ficheiros
-
Blazor exemplos de repositório GitHub (
dotnet/blazor-samples) (como fazer o download)