Nello scorso script (https://www.aspitalia.com/script/1456/Generare-File-Download-Blazor-WebAssembly.aspx) abbiamo visto come possiamo scatenare il download di un file da Blazor WebAssembly tramite un componente custom che abbiamo chiamato FileSaver. Questa tecnica può essere utile in una grande varietà di contesti, come per esempio la generazione al volo di file PDF per l'utente.
Come al solito, il primo passo è quello di aggiungere i corrispondenti pacchetti NuGet. Nel nostro caso useremo la libreria iText.
dotnet add package itext7 dotnet add package itext7.bouncy-castle-adapter
A questo punto abbiamo a disposizione un potente strumento per creare il contenuto di un file PDF direttamente in un MemoryStream. Modifichiamo allora la pagina FetchData per consentire il download di questo tipo di file:
@page "/fetchdata" @using iText.Kernel.Colors; @using iText.Kernel.Geom; @using iText.Kernel.Pdf; @using iText.Layout; @using iText.Layout.Element; @using iText.Layout.Properties; @inject FileSaver FileSaver; @* altro codice qui *@ <button class="btn btn-primary" @onclick="DownloadPdfStream"> Download forecast data in Pdf </button>
Con una tecnica del tutto analoga a quella del precedente script, possiamo iniziare a manipolare il modello a oggetti di iText per generare il file desiderato. Diamo innanzi tutto un'occhiata all'impostazione generale:
private async Task DownloadPdfStream() { using var stream = new MemoryStream(); var writer = new PdfWriter(stream); writer.SetCloseStream(false); var pdf = new PdfDocument(writer); var document = new Document(pdf, PageSize.A4); // ... qui codice che popola il document ... document.Close(); stream.Position = 0; await this.FileSaver.SaveAsAsync("forecasts.pdf", stream); }
Come possiamo notare, inizialmente costruiamo un MemoryStream che poi inviamo al corrispondente PdfWriter. Attenzione al fatto di impostare SetCloseStream a false, altrimenti questo oggetto chiuderà il MemoryStream in fase di flush dei contenuti, con il risultato da renderlo inaccessibile per il successivo download.
Successivamente, creiamo nell'ordine l'oggetto PdfDocument e finalmente il vero e proprio Document, che potremo poi popolare con il contenuto del forecast.
Una volta che il document è popolato correttamente, dobbiamo invocarne il metodo Close, così da salvare tutto il contenuto del buffer sullo stream, per poi inviarlo al nostro oggetto FileSaver che abbiamo costruito nel precedente script.
Il codice che popola il contenuto del document, è un po' tedioso, ma lo riportiamo per completezza:
// aggiungiamo un titolo alla pagina document.Add(new Paragraph("Weather forecast") .SetTextAlignment(TextAlignment.CENTER) .SetFontSize(20)); // creiamo la tabella per i forecast Table table = new Table(UnitValue.CreatePercentArray(4)).UseAllAvailableWidth(); // header table.AddHeaderCell("Date"); table.AddHeaderCell("Temp. (C)"); table.AddHeaderCell("Temp. (F)"); table.AddHeaderCell("Summary"); // righe foreach (var forecast in forecasts) { table.AddCell(forecast.Date.ToShortDateString()); table.AddCell(forecast.TemperatureC.ToString()); table.AddCell(forecast.TemperatureF.ToString()); table.AddCell(forecast.Summary); } document.Add(table);
Se abbiamo svolto i passaggi correttamente, il risultato sarà simile a quello in figura.
Attenzione a un aspetto importante: iText è disponibile gratuitamente come CommunityEdition, ma con licenza AGPLv3 (https://itextpdf.com/how-buy/AGPLv3-license), che tra le varie cose, obbliga a pubblicare il vostro progetto come open source. Alternativamente è possible acquistare una licenza commerciale.
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Persistere la ChatHistory di Semantic Kernel in ASP.NET Core Web API per GPT
Limitare le richieste lato server con l'interactive routing di Blazor 8
Aprire una finestra di dialogo per selezionare una directory in WPF e .NET 8
Utilizzare il nuovo modello GPT-4o con Azure OpenAI
Utilizzare Copilot con Azure Cosmos DB
Eseguire operazioni sui blob con Azure Storage Actions
Gestire la cancellazione di una richiesta in streaming da Blazor
Utilizzare Tailwind CSS all'interno di React: primi componenti
Rinnovare il token di una GitHub App durante l'esecuzione di un workflow
Testare l'invio dei messaggi con Event Hubs Data Explorer
Sfruttare lo stream rendering per le pagine statiche di Blazor 8
Ottimizzare le performance delle collection con le classi FrozenSet e FrozenDictionary