Condividi tramite


download di file di Blazor base ASP.NET

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 di 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 altre informazioni, vedere 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 un flusso

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 interoperabilità JavaScript (JS). 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 interoperabilità JavaScript (JS).

Avviso

L'approccio 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 fornito in un oggetto ArrayBuffer.
  • Crea un Blob oggetto per eseguire il wrapping dell'oggetto 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 Posizione JavaScript nelle app ASP.NET CoreBlazor.

Componente seguente:

  • Usa l'interoperabilità di flusso di byte nativa per garantire un trasferimento efficiente del file nel client.
  • Dispone di un metodo denominato GetFileStream per recuperare un Stream oggetto per il file scaricato nei 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 oggetto da usare come file binario generato in modo dinamico 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 DotNetStreamReferenceoggetto , 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 lato server che deve restituire un Stream oggetto 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 è un valore letterale stringa verbatim, che consente l'uso di barre rovesciata (\) in un percorso del sistema operativo Windows e virgolette doppie incorporate ("") per una virgoletta singola nel percorso. In alternativa, evitare il valore letterale stringa (@) e usare uno degli approcci seguenti:

  • Usare barre rovesciate di escape () e virgolette (\\\").
  • Usare le barre (/) nel percorso, supportate tra le piattaforme nelle app ASP.NET Core e virgolette di 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 Posizione JavaScript nelle app ASP.NET CoreBlazor.

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 altre informazioni, vedere la sezione Condivisione 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 triggerFileDownloadJavaScript (JS).

Se il componente adotta il rendering statico lato server (SSR statico), aggiungere un gestore eventi per il pulsante (addEventListener (documentazione MDN) 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 triggerFileDownloadJavaScript (JS).

Se il componente adotta il rendering statico lato server (SSR statico), aggiungere un gestore eventi per il pulsante (addEventListener (documentazione MDN) 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.

Cross-Origin Resource Sharing (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