Guida a PDFsharp: Creare file PDF con MigraDoc e PdfSharpCore

Guida a PDFsharp: Creare file PDF con MigraDoc e PdfSharpCore

PDFsharp è una libreria .NET open source per la creazione e la modifica di documenti PDF da codice C#. È sufficiente disegnare testo, linee e immagini su una pagina, chiamare il metodo Salva e si ottiene un file PDF. Non richiede un motore di rendering del browser né un eseguibile nativo. Il progetto risale al 2005 e molte fatture, report e certificati generati da back-end .NET ancora oggi passano attraverso questa libreria.

Ho scritto questo articolo per gli sviluppatori che necessitano di file PDF sul server e vogliono sapere cosa aspettarsi. Tratteremo l'integrazione tra PDFsharp e MigraDoc, quale versione installare, un primo file funzionante, i problemi relativi ai font su Linux, la recente modifica della licenza e il momento in cui è consigliabile optare per un'altra soluzione.

Cos'è PDFsharp e quali sono le sue funzionalità?

Dietro la libreria PDFsharp si cela empira Software GmbH, una piccola azienda tedesca che la mantiene in vita da quasi vent'anni. Gran parte del tempo sarà dedicato a una singola classe, XGraphics. Se avete mai disegnato su WinForms con System.Drawing.Graphics, vi sentirete a vostro agio in dieci minuti: font, pennello, coordinate x e y, via.

Nella confezione troverete:

  • Crea documenti PDF da zero con testo, forme vettoriali, linee e immagini.
  • Apri file PDF esistenti e aggiungi contenuti alle loro pagine, come timbri, filigrane o numeri di pagina.
  • Unisci e dividi documenti importando pagine da un file all'altro.
  • Incorpora e seleziona i font in modo che il file abbia lo stesso aspetto su ogni macchina
  • Aggiungi segnalibri, collegamenti e metadati del documento come titolo, autore e parole chiave.
  • Proteggi i file con password e flag di autorizzazione
  • Firma i documenti in formato digitale (a partire dalla versione 6.2)

Il processo di distribuzione è noioso, e lo dico come un complimento. Tutto è gestito tramite codice, quindi il responsabile operativo non dovrà mai installare Chrome headless su un server o cercare una DLL di Ghostscript alle 2 del mattino. Basta fare riferimento a un pacchetto NuGet, caricarlo e il gioco è fatto.

Ora, ecco il punto cruciale. Hai a disposizione solo una tela e nient'altro. Un paragrafo lungo tocca il margine inferiore? È un tuo problema. Una tabella si estende oltre la prima pagina? Anche questo è un tuo problema, a meno che tu non utilizzi MigraDoc.

PDFsharp e MigraDoc: di quale livello hai bisogno?

Stesso fornitore, stesso calendario di rilascio, ma mansioni molto diverse. MigraDoc Foundation si trova un piano sopra PDFsharp. Invece di indicargli dove inserire una stringa, gli si forniscono sezioni, paragrafi, tabelle, intestazioni, piè di pagina, stili e qualche grafico, e lui capisce dove posizionare ogni elemento. Il risultato è un PDF. O un RTF, per il collega che insiste nell'aprire tutto in Word.

In breve: PDFsharp significa "metti questo testo alle coordinate x=40, y=120". MigraDoc significa "ecco trenta righe e un'intestazione che si ripete, tu disponi le pagine".

Compito Migliore vestibilità Perché
Certificato o biglietto di una pagina con posizioni fisse PDFsharp Controllo completo su ogni coordinata
Report multipagina con tabelle e intestazioni correnti MigraDoc Impaginazione e stili automatici
Fattura con un numero variabile di voci MigraDoc Le tabelle si espandono e si suddividono su più pagine
Timbro, filigrana o numeri di pagina su un PDF esistente PDFsharp MigraDoc crea solo nuovi documenti
Unire o dividere i file esistenti PDFsharp L'importazione delle pagine è una funzionalità di PDFsharp
Grafico aziendale all'interno di un report MigraDoc Supporto grafico integrato
Composizione mista: report generato automaticamente più copertina disegnata su misura. Entrambi MigraDoc può eseguire il rendering su una pagina PDFsharp

Nei progetti reali, di solito si finisce per usare entrambi i metodi. Il testo del documento viene inserito tramite MigraDoc, mentre una copertina disegnata a mano o un timbro su un PDF di un fornitore vengono inseriti tramite il livello inferiore. In ogni caso, non si può evitare di installare PDFsharp, perché il pacchetto MigraDoc lo include come dipendenza.

Spiegazione delle build di PDFsharp: Core Build, GDI+ e WPF

I nuovi utenti di solito si ritrovano in fondo alla lista dei pacchetti in NuGet. PDFsharp 6 è disponibile in tre versioni, ognuna con il proprio gemello MigraDoc.

Pacchetto NuGet Costruire Piattaforme Caratteri e immagini
PDFsharp / PDFsharp-MigraDoc Nucleo Windows, Linux, macOS Richiede un risolutore di font; immagini BMP, PNG, JPEG
PDFsharp-GDI / PDFsharp-MigraDoc-GDI GDI+ Solo finestre Utilizza i caratteri installati tramite System.Drawing
PDFsharp-WPF / PDFsharp-MigraDoc-WPF WPF Solo finestre Utilizza i font installati tramite WPF

I pacchetti attualmente disponibili supportano .NET 8, 9 e 10, oltre a .NET Standard 2.0 e .NET Framework 4.6.2. Quindi, praticamente tutto ciò che è ancora in fase di sviluppo è coperto, da un vecchio strumento WinForms a una nuovissima API ASP.NET Core.

Applicazione console, API web, Docker, Funzioni Azure, qualsiasi cosa su Linux? Build di base. GDI+ o WPF hanno senso solo per un'applicazione desktop Windows in cui si desiderano i font di sistema o un'anteprima in un controllo nativo. Qualcuno su Stack Overflow una volta ha chiesto se la sua applicazione console avesse bisogno della versione WPF. Non ne aveva bisogno.

Guida PDFsharp

Come installare PDFsharp da NuGet in Visual Studio

Troverete ancora discussioni sui forum risalenti all'epoca di WinForms che vi consigliano di scaricare un file ZIP, estrarre una DLL e aggiungere manualmente il riferimento. Ignoratele. Installate PDFsharp tramite NuGet; il gestore di pacchetti tiene traccia delle versioni, quindi non dovrete farlo voi.

  1. Apri la soluzione in Visual Studio e fai clic con il pulsante destro del mouse sul progetto in Esplora soluzioni.
  2. Seleziona Gestisci pacchetti NuGet , passa alla scheda Sfoglia e cerca "PDFsharp".
  3. Seleziona PDFsharp (versione Core) o PDFsharp-MigraDoc se hai bisogno anche dell'impaginazione del documento. Verifica che l'editore sia empira Software GmbH.
  4. Fai clic su Installa e accetta la richiesta di licenza.
  5. Compila il progetto una volta per verificare che il pacchetto sia stato ripristinato correttamente.

Gli utenti del terminale possono saltare questo passaggio:

bash dotnet add package PDFsharp dotnet add package PDFsharp-MigraDoc

All'interno della Console di Gestione Pacchetti, la stessa cosa è Install-Package PDFsharp. E per favore, non mescolate le build. Ho visto un team perdere un intero pomeriggio a causa di conflitti di tipo perché un progetto faceva riferimento a PDFsharp e il progetto adiacente includeva PDFsharp-GDI.

Il tuo primo documento PDF con PDFsharp in C

Di seguito viene descritto il programma più semplice in grado di generare un file PDF di una sola pagina. Funziona con la versione Core di qualsiasi sistema operativo, a condizione che sia configurato un risolutore di font (vedi sezione successiva).

```csharp
Utilizzo di PdfSharp.Drawing;
utilizzando PdfSharp.Pdf;

// PDFsharp 6.5+ richiede la scelta di una licenza prima del primo utilizzo
PdfSharpLicense.SetAgplLicense();

var document = new PdfDocument();
document.Info.Title = "Ciao PDFsharp";

PdfPage page = document.AddPage();
XGraphics gfx = XGraphics.FromPdfPage(page);

var font = new XFont("Arial", 20, XFontStyleEx.Bold);
gfx.DrawString("Ciao, PDFsharp!", font, XBrushes.Black,
nuovo XRect(0, 0, page.Width.Point, page.Height.Point),
XStringFormats.Center);

document.Save("hello.pdf");
```

Ogni programma PDFsharp segue questo schema: documento, pagina, XGraphics, disegna, salva. Le unità sono punti (1/72 di pollice) e l'origine si trova nell'angolo in alto a sinistra. Nella versione 6.2.x, eliminare la riga relativa alla licenza. Tale API è stata introdotta solo nella versione 6.5.0.

E la versione di MigraDoc:

```csharp
Utilizzo di MigraDoc.DocumentObjectModel;
Utilizzo di MigraDoc.Rendering;

var doc = new Document();
Sezione sezione = doc.AddSection();
sezione.AggiungiParagrafo("Ciao, MigraDoc!");

var renderer = nuovo PdfDocumentRenderer { Document = doc };
renderer.RenderDocument();
renderer.PdfDocument.Save("ciao-migradoc.pdf");
```

Nessuna coordinata da nessuna parte. Inserisci 500 paragrafi e otterrai un numero di pagine pari a quello necessario, senza alcun codice di impaginazione da parte tua.

I font nella build principale di PDFsharp: il problema del resolver

Chiedete in giro e sentirete spesso parlare di font. Le build GDI+ e WPF si limitano a leggere i font TrueType installati da Windows. La build Core non può dare nulla per scontato, perché un container Linux "slim" spesso non ha font utilizzabili. Quindi il primo deployment con Docker tende a terminare con un'eccezione relativa all'impossibilità di trovare un font appropriato.

La soluzione consiste in un risolutore di font, una classe che implementa l'interfaccia IFontResolver. Essa dispone di due metodi:

  • ResolveTypeface associa la famiglia e lo stile richiesti (ad esempio, "Arial", grassetto) al nome di un carattere.
  • GetFont restituisce i byte grezzi del file TTF per quel nome di volto

Registralo una sola volta all'avvio tramite GlobalFontSettings.FontResolver, prima che venga creato il primo XFont.

```csharp
classe pubblica AppFontResolver : IFontResolver
{
public FontResolverInfo? ResolveTypeface(string family, bool bold, bool italic)
=> new FontResolverInfo(bold ? "Inter-Bold" : "Inter-Regular");

public byte[]? GetFont(string faceName) => File.ReadAllBytes(Path.Combine(AppContext.BaseDirectory, "Fonts", faceName + ".ttf"));

}

GlobalFontSettings.FontResolver = new AppFontResolver();
```

Cose da sapere prima di provarci:

  • Conserva i tuoi file TTF in una cartella Fonts all'interno del progetto e impostali in modo che vengano copiati nella directory di output, oppure incorporali come risorse in modo che l'immagine contenitore li includa sempre.
  • La versione 6.2.0 ha rimosso il vecchio CoreBuildFontResolver. Su Windows o WSL2 è possibile ripristinare un comportamento simile con GlobalFontSettings.UseWindowsFontsUnderWindows, ma questo non ha alcun effetto su Linux o macOS.
  • Il repository ufficiale degli esempi include un SubstitutingFontResolver che puoi copiare come punto di partenza.
  • Prima di incorporare un carattere commerciale nei file generati, verifica la licenza del font. I font open source come Inter, Roboto o Noto non presentano alcun problema.

Con il resolver installato, l'output appare identico su Windows, Linux e macOS.

Unire, firmare e proteggere i file con PDFsharp 6

Molti team non creano mai un documento da zero. Utilizzano la libreria per incollare, timbrare o bloccare file già esistenti. L'unione richiede solo poche righe di codice: apri ogni file sorgente in modalità di importazione e copia le pagine.

csharp var output = new PdfDocument(); foreach (var path in new[] { "part1.pdf", "part2.pdf" }) { using var input = PdfReader.Open(path, PdfDocumentOpenMode.Import); foreach (PdfPage p in input.Pages) output.AddPage(p); } output.Save("merged.pdf");

La suddivisione segue lo stesso ciclo al contrario, generando un file di output per ogni pagina o intervallo. Per la protezione, document.SecuritySettings richiede una password utente, una password del proprietario e i flag di autorizzazione (stampa, copia del testo e così via).

Due funzionalità a lungo richieste sono finalmente arrivate nella versione 6.2:

  • Firme digitali basate su CMS. Un firmatario predefinito è incluso in un assembly PDFsharp.Cryptography separato, ed è possibile integrarne uno personalizzato implementando IDigitalSigner. Il supporto per il server di timestamp funziona sulle versioni moderne di .NET, ma non sulla versione basata su .NET Framework.
  • Output in formato PDF/A per l'archiviazione. La documentazione ufficiale lo descrive come funzionante "con alcune limitazioni" e ancora in fase di sviluppo, pertanto si consiglia di convalidare il risultato con un verificatore di PDF/A prima di utilizzarlo ai fini della conformità.

Questa versione ha introdotto anche glifi emoji a colori e un'implementazione gestita di MD5, aspetto importante se si opera secondo le regole FIPS o in Blazor.

Repository di PDFsharp, fork di PdfSharpCore e versioni 1.x

Cercando PDFsharp su GitHub, troverete una manciata di progetti con un nome quasi identico. La colpa è della storia.

La vecchia linea 1.x (1.50, 1.51) funzionava solo su .NET Framework. Quando è uscito .NET Core, la gente non aveva voglia di aspettare, quindi lo ha adattato autonomamente. PdfSharpCore, iniziato da Stefan Steiger e ripreso in seguito da altri fork, è quello più conosciuto. Ha eliminato GDI+ e ha reso il codice eseguibile su Linux anni prima del rilascio ufficiale.

Poi è arrivato PDFsharp 6: una vera e propria riscrittura su .NET moderno con una build Core ufficiale multipiattaforma. Le versioni derivate hanno perso gran parte della loro ragione d'essere.

Progetto Manutentore Piattaforme Stato
PDFsharp 6.x (repository empira/PDFsharp) empira Software GmbH .NET 8–10, .NET Standard 2.0, .NET Framework 4.6.2 Mantenuto attivamente
PDFsharp 1.5x empira Software GmbH Solo .NET Framework Il codice sorgente è conservato su GitHub e non viene più aggiornato.
PdfSharpCore e le sue varianti Comunità .NET Core / .NET Standard 2.0 Varia a seconda della versione, aggiornamenti più lenti
PDFsharp-MigraDoc 6.x empira Software GmbH Uguale a PDFsharp 6 Mantenuto attivamente

Quindi, la discussione "PdfSharp vs PdfSharpCore" che continua a ripresentarsi su Reddit? Nuovo progetto, pacchetti ufficiali. Mantenete un fork solo se il vecchio codice ne dipende già e la migrazione non vale la pena di uno sprint in questo momento. E se la documentazione vi sembra scarsa, consultate il repository di esempi separato di empira. Le sue cartelle e i suoi file contengono esempi eseguibili, il che è molto meglio che andare a tentoni.

PDFsharp è gratuito? Modifiche alla licenza in PDFsharp 6.5

Per gran parte della sua esistenza, sì. Era rilasciato con licenza MIT, il che significa che era utilizzabile a fini commerciali praticamente senza vincoli. Tutte le versioni fino alla 6.2.4 inclusa lo sono ancora.

La versione 6.5.0 ha cambiato le cose. La libreria ora ha una doppia licenza:

  • AGPL (gratuita). La si abilita chiamando PdfSharpLicense.SetAgplLicense() prima di utilizzare la libreria. La licenza AGPL richiede di rendere disponibile il codice sorgente agli utenti, inclusi quelli che interagiscono con il software tramite una rete, quindi non è adatta per SaaS proprietari.
  • Licenza commerciale. Si acquista una chiave di licenza dal fornitore e la si carica con PdfSharpLicense.LoadLicense(...). Questo elimina gli obblighi della licenza AGPL.

Dalla versione 6.5.0 in poi, il codice deve selezionarne una esplicitamente. Le anteprime della versione 7.0 funzionano allo stesso modo.

In pratica:

  • I progetti open source compatibili con la licenza AGPL possono continuare a utilizzare la versione più recente gratuitamente.
  • I prodotti closed-source possono scegliere tra l'acquisto di una licenza commerciale o il mantenimento della versione 6.2.x, che rimane sotto licenza MIT. Rimanere su questa versione significa perdere i futuri aggiornamenti, quindi è importante valutare attentamente questo aspetto.
  • Qualunque sia la tua scelta, leggi attentamente il testo della licenza e fallo firmare al tuo team legale. Questa guida non costituisce consulenza legale.

Guida PDFsharp

Dove PDFsharp non è all'altezza e con cosa abbinarlo

La biblioteca svolge bene il suo lavoro. Il compito è solo limitato e le stesse lacune emergono in ogni discussione del forum.

  • Nessuna conversione da HTML a PDF. PDFsharp non esegue il rendering di HTML o CSS. Esiste un componente aggiuntivo della community, HtmlRenderer.PdfSharp, ma supporta solo HTML 4.01 e CSS di livello 2, quindi i layout moderni con flexbox o grid non saranno compatibili. I team che necessitano di modelli HTML solitamente optano per un renderer per browser headless.
  • JavaScript non è consentito. Grafici o contenuti creati lato client non possono essere acquisiti.
  • Nessuna conversione in immagini. PDFsharp non può convertire una pagina PDF in un'immagine PNG per miniature o anteprime. Per questo è necessario un rasterizzatore separato.
  • Estrazione del testo limitata. È possibile scorrere il flusso di contenuto, ma non esiste un'API di alto livello che restituisca testo pulito con le posizioni. PdfPig, una libreria open-source separata, è stata creata specificamente per la lettura e l'estrazione del testo.
  • Supporto parziale per i moduli. La compilazione semplice con AcroForm funziona; i moduli complessi con script sono un'altra storia.
  • Le tabelle richiedono MigraDoc. Con PDFsharp standard, l'altezza di ogni riga viene calcolata manualmente.

Ciò non significa che sia una scelta sbagliata. I documenti basati sui dati, come fatture, estratti conto, etichette e certificati, sono il suo punto di forza, e l'ingombro è minimo. Le copie fedeli al pixel delle pagine web, invece, non lo sono.

PDFsharp per fatture e ricevute di pagamento relative a criptovalute.

Le ricevute sono probabilmente il documento più comune che le persone creano con PDFsharp. Le ricevute di criptovalute sono un po' più complesse di quelle delle carte di credito. La buona notizia è che, una volta che il gateway di pagamento intercetta il tuo webhook (una callback HTTP inviata quando lo stato del pagamento cambia), hai a disposizione tutti i dati. Non c'è bisogno di cercare altrove.

Ecco cosa ci scriverei:

  • ID dell'ordine o della fattura e dati del commerciante
  • Importo in criptovaluta e relativo equivalente in valuta fiat al momento del pagamento.
  • Moneta e rete (ad esempio, USDT su TRON rispetto a USDT su Ethereum)
  • Hash della transazione, in modo che il cliente possa verificarlo su un block explorer
  • Un indirizzo del portafoglio di ricezione abbreviato e il tempo di conferma
  • Un codice QR che rimanda alla pagina della transazione o della fattura.

Usate caratteri a spaziatura fissa per hashtag e indirizzi. I clienti li leggono uno per uno, e in Arial uno zero e una O maiuscola sembrano gemelli. Se l'hashtag è troppo largo, mandatelo a capo; un testo di 6 punti non serve a nessuno. Incorporate i font, salvate il file con l'ordine e firmatelo se il vostro commercialista dovesse mai richiedervi una ricevuta.

Nessuno di questi passaggi riguarda l'effettivo incasso del denaro. Per questa fase, è necessario utilizzare un gateway come Plisio . Questo gateway accetta BTC, USDT e molte altre criptovalute, genera la fattura e chiama il tuo endpoint ogni volta che lo stato della transazione cambia. Il tuo gestore inoltra i dati a MigraDoc e l'acquirente riceve una ricevuta con il tuo logo direttamente sulla pagina di ringraziamento.

Conclusione

Continuo a tornare a PDFsharp per un motivo: è leggero e non crea problemi. La versione Core funziona ovunque sia possibile utilizzare .NET e MigraDoc si occupa del layout quando una semplice area di lavoro non è sufficiente. Tre cose da definire subito: quale versione scegliere, come vengono caricati i font e quale licenza utilizzare, ora che la versione 6.5 è diventata AGPL. Stampate dati, non pagine web, e durerà per anni.

Qualsiasi domanda?

Generazione di PDF principalmente da codice .NET. Ad esempio, fatture, report, etichette di spedizione, certificati. È utile anche per unire e dividere documenti, o per aggiungere numeri di pagina e filigrane a PDF creati da altri. Con MigraDoc come strumento aggiuntivo, anche i documenti lunghi con tabelle e grafici diventano un gioco da ragazzi.

Fino alla versione 6.2.4, sì, è sotto licenza MIT e puoi includerlo nei prodotti a pagamento. Dalla versione 6.5.0 in poi, la strada si biforca. L’opzione AGPL è gratuita ma ti obbliga a condividere il codice sorgente; quella commerciale è a pagamento e non prevede restrizioni. Il codice di avvio deve specificare quale opzione scegliere.

No. Non c’è alcun motore HTML o CSS al suo interno. Un componente aggiuntivo della community chiamato HtmlRenderer.PdfSharp ci prova, ma si ferma a HTML 4.01 e CSS 2, quindi qualsiasi cosa creata con flexbox o grid non funziona. Per le vere pagine web si usa un convertitore integrato in un browser headless.

Tramite NuGet. Fai clic con il pulsante destro del mouse sul progetto in Visual Studio, seleziona Gestisci pacchetti NuGet e cerca "PDFsharp". Da terminale, il comando `dotnet add package PDFsharp` fa al caso tuo. Vuoi anche tabelle e impaginazione? Aggiungi PDFsharp-MigraDoc. Evita il vecchio trucco di copiare manualmente le DLL.

Layout fissi e modifiche a file esistenti: PDFsharp. Tutto ciò che riguarda testo che scorre, tabelle che si espandono e pagine che si interrompono automaticamente: MigraDoc. Onestamente, probabilmente finirai per usarli entrambi, e dato che MigraDoc funziona sopra PDFsharp, vanno d’accordo.

PDFsharp 6 è compatibile con .NET 8, 9 e 10, oltre a .NET Standard 2.0 e .NET Framework 4.6.2. La versione Core funziona su Windows, Linux e macOS. Le versioni GDI+ e WPF sono disponibili solo per Windows. Se si utilizza Linux, è necessario configurare prima un risolutore di font, altrimenti si potrebbero verificare errori relativi ai font.

Ready to Get Started?

Create an account and start accepting payments – no contracts or KYC required. Or, contact us to design a custom package for your business.

Make first step

Always know what you pay

Integrated per-transaction pricing with no hidden fees

Start your integration

Set up Plisio swiftly in just 10 minutes.