Realizzando rich web application con Blazor, molto spesso può essere necessario esportare dei dati in un file. Tramite Blazor, possiamo facilmente generare questi file sul browser dell'utente - e quindi senza scomodare il server - per poi consentirne il download.
Concentriamoci per prima cosa su quest'ultimo aspetto: per eseguire il download di un file da browser, a partire da uno stream di dati, abbiamo bisogno di utilizzare del codice JavaScript. Per esempio possiamo creare un modulo come il seguente, all'interno di wwwroot, usando il codice descritto nella documentazione ufficiale di Microsoft (https://learn.microsoft.com/en-us/aspnet/core/blazor/file-downloads?view=aspnetcore-7.0#download-from-a-stream):
export async function downloadFileFromStream(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);
}Si tratta di uno snipped JavaScript che accetta uno stream in input che utilizza per costruire poi un oggetto di tipo Blob. Il link a questo oggetto viene poi associato a un link invisibile, il cui evento click avvierà il download dal browser.
A questo punto, possiamo creare un componente, che chiameremo FileSaver, che rappresenterà il nostro wrapper C# sulla funzione che abbiamo visto in alto.
public class FileSaver
{
private Lazy<Task<IJSObjectReference>> _downloadModule;
public FileSaver(IJSRuntime js)
{
_downloadModule = new Lazy<Task<IJSObjectReference>>(() => js.InvokeAsync<IJSObjectReference>("import",
"./js/downloadFileFromStream.js").AsTask());
}
public async Task SaveAsAsync(string fileName, Stream stream)
{
var js = await _downloadModule.Value;
using var streamRef = new DotNetStreamReference(stream: stream);
await js.InvokeVoidAsync("downloadFileFromStream", fileName, streamRef);
}
public async ValueTask DisposeAsync()
{
if (_downloadModule.IsValueCreated)
{
await (await _downloadModule.Value).DisposeAsync();
}
}
}Questa classe, come prima cosa, sfrutta un oggetto Lazy<T> per implementare la logica di inizializzazione con JavaScript, in cui viene referenziato il modulo che abbiamo creato nello step precedente.
Poi espone un metodo SaveAsAsync, che non fa altro che invocare la funzione downloadFileFromStream, passando lo stream C#.
Ovviamente, implementa anche l'interfaccia IAsyncDisposable per distruggere la reference a JavaScript.
Dopo aver registrato questo servizio nell'IoC container
public static async Task Main(string[] args)
{
// ... altro codice qui ...
builder.Services.AddSingleton<FileSaver>();
await builder.Build().RunAsync();
}possiamo finalmente utilizzarlo in una delle nostre pagine.
Per esempio, immaginiamo di voler esportare il WeatherForecast della pagina FetchData in formato CSV.
Dopo aver referenziato il package CsvHelper
dotnet add package csvhelper
non dobbiamo far altro che aggiungere un apposito button al markup:
.. altro codice qui ..
<button class="btn btn-primary" @onclick="DownloadFileFromStream">
Download forecast data in CSV
</button>Il metodo DownloadFileFromStream non farà altro che generare un MemoryStream con il contenuto desiderato, e inviarlo al FileSaver che abbiamo creato:
private async Task DownloadFileFromStream()
{
using var stream = new MemoryStream();
using var writer = new StreamWriter(stream, leaveOpen:true);
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
{
csv.WriteRecords(forecasts);
}
stream.Position = 0;
await this.FileSaver.SaveAsAsync("forecasts.csv", stream);
}Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Gestire il ciclo di vita di AbortController in Javascript
Effettuare chiamate API tramite GitHub App
Mappare una complex property di una entity su un campo JSON
Costruire endpoint SSE in ASP.NET Core
Operazioni tra insiemi di array in Javascript
Migliorare accessibilità e interazioni nelle pagine HTML con gli attributi inert e autofocus
Effettuare un clone parziale di un repository di GitHub
Introduzione a GitHub Copilot CLI
Semplificare la gestione dei modelli con Azure AI Foundry Model Router
Supporto nativo a JSON in SQL Server 2025
Usare la parola chiave field per semplificare la scrittura di proprietà in C#
Integrare il Docker Model Runner in un workflow di GitHub
I più letti di oggi
- Effettuare il multi-checkout in linea nelle pipeline di Azure DevOps
- Accedere a risorse e immagini in Windows Store app di Windows 8
- Alleggerire le applicazioni WPF sfruttando gli oggetti Freezable
- Permettere il Drag-and-drop solo su zone predefinite con Silverlight 2.0
- Consumare dati binari in realtime lato client con ASP.NET Core SignalR
- Effetto turnstile su tutte le pagine con il Windows Phone Toolkit
- Personalizare l'icona e le funzionalità di un sito web per iOS e IE
- Caricamenti veloci da CDN e fallback locale con ASP.NET Core
- Utilizzare dati in formato XML in XAML
- Accedere a dati esposti con WebService con Silverlight 1.0


