Condividi tramite


download di file ASP.NET Core Blazor

Nota

Questa non è la versione più recente di questo articolo. Per la versione corrente, vedere la versione .NET 9 di questo articolo.

Avviso

Questa versione di ASP.NET Core non è più supportata. Per altre informazioni, vedere i criteri di supporto di .NET e .NET Core. Per la versione corrente, vedere la versione .NET 9 di questo articolo.

Importante

Queste informazioni si riferiscono a un prodotto non definitive che può essere modificato in modo sostanziale prima che venga rilasciato commercialmente. Microsoft non riconosce alcuna garanzia, espressa o implicita, in merito alle informazioni qui fornite.

Per la versione corrente, vedere la versione .NET 9 di questo articolo.

Questo articolo illustra come scaricare i file nelle Blazor app.

Download dei file

Questo articolo illustra gli approcci per gli scenari seguenti, in cui un file non deve essere aperto da un browser, ma scaricato e salvato nel client:

Quando si scaricano file da un'origine diversa da quella dell'app, si applicano considerazioni sulla condivisione di risorse tra le origini (CORS). Per ulteriori informazioni, consultare la sezione Condivisione risorse tra le origini (CORS).

Considerazioni relative alla sicurezza

Prestare attenzione quando si fornisce agli utenti la possibilità di scaricare file da un server. I cyberattacker possono eseguire attacchi Denial of Service (DoS), attacchi di sfruttamento delle API o tentare di compromettere reti e server in altri modi.

I passaggi di sicurezza che riducono la probabilità di un attacco riuscito sono:

  • Scaricare i file da un'area di download di file dedicata nel server, preferibilmente da un'unità non di sistema. L'uso di un percorso dedicato semplifica l'imposizione di restrizioni di sicurezza per i file scaricabili. Disabilitare le autorizzazioni di esecuzione nell'area di download dei file.
  • I controlli di sicurezza lato client sono facili da aggirare da parte di utenti malintenzionati. Eseguire sempre controlli di sicurezza sul lato client anche nel server.
  • Non ricevere file da utenti o altre origini non attendibili e quindi rendere i file disponibili per il download immediato senza eseguire controlli di sicurezza sui file. Per altre informazioni, vedere Caricare file in ASP.NET Core.

Scaricare da uno streaming

Questa sezione si applica ai file con dimensioni massime di 250 MB.

L'approccio consigliato per il download di file relativamente piccoli (< 250 MB) consiste nel trasmettere il contenuto del file a un buffer di dati binari non elaborati nel client con JS JavaScript (). Questo approccio è efficace per i componenti che adottano una modalità di rendering interattiva, ma non i componenti che adottano il rendering statico lato server (SSR statico).

L'approccio consigliato per il download di file relativamente piccoli (< 250 MB) consiste nel trasmettere il contenuto del file a un buffer di dati binari non elaborati nel client con JS JavaScript ().

Avviso

L'approccio descritto in questa sezione legge il contenuto del file in un oggetto JS ArrayBuffer. Questo approccio carica l'intero file nella memoria del client, che può compromettere le prestazioni. Per scaricare file relativamente grandi (>= 250 MB), è consigliabile seguire le indicazioni nella sezione Download from a URL (Scarica da un URL ).

La funzione seguente downloadFileFromStreamJS :

  • Legge il flusso di dati fornito in un oggetto ArrayBuffer.
  • Crea un Blob per avvolgere il ArrayBuffer.
  • Crea un URL dell'oggetto da usare come indirizzo di download del file.
  • Crea un elemento HTMLAnchorElement (<a> ).
  • Assegna il nome del file (fileName) e l'URL (url) per il download.
  • Attiva il download attivando un click evento sull'elemento di ancoraggio.
  • Rimuove l'elemento di ancoraggio.
  • Revoca l'URL dell'oggetto (url) chiamando URL.revokeObjectURL. Si tratta di un passaggio importante per assicurarsi che la memoria non venga persa nel 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>

Nota

Per indicazioni generali sulla JS posizione e i suggerimenti per le app di produzione, vedere Blazor ASP.NET Core.

Componente seguente:

  • Usa l'interoperabilità di flusso di byte nativa per garantire un trasferimento efficiente del file al client.
  • Dispone di un metodo denominato GetFileStream per recuperare un Stream per il file scaricato sui client. Gli approcci alternativi includono il recupero di un file dall'archiviazione o la generazione dinamica di un file nel codice C#. Per questa dimostrazione, l'app crea un file di 50 KB di dati casuali da una nuova matrice di byte (new byte[]). i byte vengono incapsulati con un MemoryStream per essere utilizzati come file binario generato dinamicamente dell'esempio.
  • Il metodo DownloadFileFromStream:
    • Recupera l'oggetto Stream da GetFileStream.
    • Specifica un nome di file quando il file viene salvato nel computer dell'utente. L'esempio seguente denomina il file quote.txt.
    • Esegue il wrapping di Stream in un DotNetStreamReference, che consente di trasmettere i dati del file al client.
    • Richiama la downloadFileFromStreamJS funzione per accettare i dati nel client.

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);
    }
}

Per un componente in un'app sul lato server che deve restituire un Stream per un file fisico, il componente può chiamare File.OpenRead, come illustrato nell'esempio seguente:

private Stream GetFileStream() => File.OpenRead(@"{PATH}");

Nell'esempio precedente il {PATH} segnaposto è il percorso del file. Il @ prefisso indica che la stringa è una stringa letterale verbatim, che consente l'uso di una barra rovesciata (\) in un percorso del sistema operativo Windows e di virgolette doppie ("") all'interno di un singolo elemento nel percorso. In alternativa, evitare il valore letterale stringa (@) e usare uno degli approcci seguenti:

  • Utilizzare le barre rovesciate di escape (\\) e le virgolette (\").
  • Usare barre oblique (/) nel percorso, che sono supportate su tutte le piattaforme nelle app ASP.NET Core, e virgolette con escape (\").

Scaricare da un URL

Questa sezione si applica ai file di dimensioni relativamente grandi, in genere di 250 MB o superiori.

L'approccio consigliato per il download di file relativamente grandi (>= 250 MB) con componenti o file di cui è stato eseguito il rendering interattivo di qualsiasi dimensione per i componenti sottoposti a rendering statico consiste nell'attivare JS un elemento di ancoraggio con il nome e l'URL del file.

L'approccio consigliato per il download di file relativamente grandi (>= 250 MB) consiste nell'attivare JS un elemento di ancoraggio con il nome e l'URL del file.

L'esempio in questa sezione usa un file di download denominato quote.txt, che viene inserito in una cartella denominata files nella radice Web dell'app (wwwroot cartella). L'uso della files cartella è solo a scopo dimostrativo. È possibile organizzare i file scaricabili in qualsiasi layout di cartella all'interno della radice Web (wwwroot cartella) preferita, inclusa la gestione dei file direttamente dalla wwwroot cartella.

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 funzione seguente triggerFileDownloadJS :

  • Crea un elemento HTMLAnchorElement (<a> ).
  • Assegna il nome del file (fileName) e l'URL (url) per il download.
  • Attiva il download attivando un click evento sull'elemento di ancoraggio.
  • Rimuove l'elemento di ancoraggio.
<script>
  window.triggerFileDownload = (fileName, url) => {
    const anchorElement = document.createElement('a');
    anchorElement.href = url;
    anchorElement.download = fileName ?? '';
    anchorElement.click();
    anchorElement.remove();
  }
</script>

Nota

Per indicazioni generali sulla JS posizione e i suggerimenti per le app di produzione, vedere Blazor ASP.NET Core.

Il componente di esempio seguente scarica il file dalla stessa origine usata dall'app. Se si tenta di scaricare il file da un'origine diversa, configurare la condivisione di risorse tra le origini (CORS). Per ulteriori informazioni, vedere la sezione Condivisione delle risorse tra le origini (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);
    }
}

Per i componenti interattivi, il pulsante nell'esempio precedente chiama il DownloadFileFromURL gestore per richiamare la funzione JSJavaScript (triggerFileDownload).

Se il componente adotta il rendering statico lato server (SSR statico), aggiungere un gestore eventi per il pulsante (addEventListener) per chiamare triggerFileDownload seguendo le indicazioni riportate in ASP.NET Core Blazor JavaScript con rendering statico lato server (SSR statico).

@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);
    }
}

Per i componenti interattivi, il pulsante nell'esempio precedente chiama il DownloadFileFromURL gestore per richiamare la funzione JSJavaScript (triggerFileDownload).

Se il componente adotta il rendering statico lato server (SSR statico), aggiungere un gestore eventi per il pulsante (addEventListener) per chiamare triggerFileDownload seguendo le indicazioni riportate in ASP.NET Core Blazor JavaScript con rendering statico lato server (SSR statico).

@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);
    }
}

Modificare la porta nell'esempio precedente in modo che corrisponda alla porta di sviluppo localhost dell'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);
    }
}

Modificare la porta nell'esempio precedente in modo che corrisponda alla porta di sviluppo localhost dell'ambiente.

Condivisione delle risorse tra origini diverse (CORS)

Senza eseguire ulteriori passaggi per abilitare la condivisione di risorse tra le origini (CORS) per i file che non hanno la stessa origine dell'app, il download dei file non passerà i controlli CORS eseguiti dal browser.

Per altre informazioni su CORS con app ASP.NET Core e altri prodotti e servizi Microsoft che ospitano file per il download, vedere le risorse seguenti:

Risorse aggiuntive