Guide PDFsharp : Créer des fichiers PDF avec MigraDoc et PdfSharpCore

Guide PDFsharp : Créer des fichiers PDF avec MigraDoc et PdfSharpCore

PDFsharp est une bibliothèque .NET open source permettant de créer et de modifier des documents PDF à partir de code C#. Il suffit de dessiner du texte, des lignes et des images sur une page, d'appeler la méthode Save, et le fichier PDF est généré. Aucun moteur de navigateur, aucun binaire natif. Ce projet remonte à 2005, et de nombreuses factures, rapports et certificats générés par les systèmes .NET utilisent encore cette bibliothèque aujourd'hui.

J'ai écrit ce guide pour les développeurs qui ont besoin de gérer des PDF sur leur serveur et qui souhaitent en connaître les implications. Nous aborderons la complémentarité de PDFsharp et MigraDoc, la version à installer, la création d'un premier fichier fonctionnel, les problèmes de polices sous Linux, le récent changement de licence et les situations où il est préférable d'opter pour une autre solution.

Qu'est-ce que PDFsharp et que peut-il faire ?

Derrière la bibliothèque PDFsharp se cache empira Software GmbH, une petite entreprise allemande qui la maintient en activité depuis près de vingt ans. L'essentiel du temps est consacré à une seule classe : XGraphics. Si vous avez déjà utilisé System.Drawing.Graphics pour le dessin dans WinForms, vous vous sentirez comme chez vous en dix minutes : police, pinceau, axes x et y, et c'est parti !

Dans la boîte, vous trouverez :

  • Créez des documents PDF à partir de zéro avec du texte, des formes vectorielles, des lignes et des images.
  • Ouvrez des fichiers PDF existants et ajoutez du contenu à leurs pages, comme des tampons, des filigranes ou des numéros de page.
  • Fusionnez et divisez des documents en important des pages d'un fichier dans un autre.
  • Incorporez et sous-ensemblez les polices pour que le fichier ait le même aspect sur chaque machine.
  • Ajoutez des signets, des liens et des métadonnées au document, comme le titre, l'auteur et les mots-clés.
  • Protéger les fichiers avec des mots de passe et des indicateurs d'autorisation
  • Signez des documents numériquement (depuis la version 6.2)

Le déploiement est d'une simplicité enfantine, et c'est un compliment. Tout est géré en code, donc votre administrateur système n'aura jamais à installer Chrome sans interface graphique ni à chercher une DLL Ghostscript à 2 heures du matin. Il suffit de référencer un package NuGet, de le pousser, et c'est tout.

Voici le hic : vous obtenez une page blanche, et rien de plus. Un long paragraphe atteint la marge inférieure ? C’est votre problème. Un tableau déborde sur la première page ? C’est aussi le vôtre, sauf si vous utilisez MigraDoc.

PDFsharp et MigraDoc : de quelle couche avez-vous besoin ?

Même fournisseur, même calendrier de publication, mais des tâches bien différentes. MigraDoc Foundation se trouve juste au-dessus de PDFsharp. Au lieu de lui indiquer l'emplacement d'une chaîne de caractères, on lui fournit des sections, des paragraphes, des tableaux, des en-têtes, des pieds de page, des styles et quelques graphiques, et il se charge de tout agencer. Le résultat ? Un PDF. Ou un RTF, pour le collègue qui insiste pour tout ouvrir dans Word.

En résumé : PDFsharp signifie « placez ce texte à x=40, y=120 ». MigraDoc signifie « voici trente lignes et un en-tête qui se répète, à vous de trier les pages ».

Tâche Meilleure adaptation Pourquoi
Certificat ou billet d'une page avec positions fixes PDFsharp Contrôle total sur chaque coordonnée
Rapport multipage avec tableaux et en-têtes courants MigraDoc Pagination et styles automatiques
Facture comportant un nombre variable de lignes MigraDoc Les tableaux s'étendent et se divisent sur plusieurs pages.
Tampon, filigrane ou numéros de page sur un PDF existant PDFsharp MigraDoc ne crée que de nouveaux documents
Fusionner ou diviser les fichiers existants PDFsharp L'importation de pages est une fonctionnalité de PDFsharp
Graphique d'entreprise dans un rapport MigraDoc Prise en charge intégrée des graphiques
Mixte : rapport généré et couverture personnalisée Les deux MigraDoc peut être rendu sur une page PDFsharp

Dans la plupart des projets, on retrouve les deux : le texte principal via MigraDoc, une couverture dessinée à la main ou un tampon sur un PDF fourni par un prestataire externe via la couche inférieure. De toute façon, il est quasiment impossible d'éviter l'installation de PDFsharp, car le paquet MigraDoc l'intègre comme dépendance.

Explication des différentes configurations de PDFsharp : configuration de base, GDI+ et WPF

Les nouveaux utilisateurs se retrouvent généralement bloqués juste après l'étape suivante dans la liste des packages NuGet. PDFsharp 6 est disponible en trois versions, chacune avec son propre équivalent MigraDoc.

package NuGet Construire Plateformes Polices et images
PDFsharp / PDFsharp-MigraDoc Cœur Windows, Linux, macOS Nécessite un résolveur de polices ; images BMP, PNG, JPEG
PDFsharp-GDI / PDFsharp-MigraDoc-GDI GDI+ Windows uniquement Utilise les polices installées via System.Drawing
PDFsharp-WPF / PDFsharp-MigraDoc-WPF WPF Windows uniquement Utilise les polices installées via WPF

Les packages actuels ciblent .NET 8, 9 et 10, ainsi que .NET Standard 2.0 et .NET Framework 4.6.2. Ainsi, pratiquement tout ce qui est encore en développement est couvert, d'un outil WinForms obsolète à une toute nouvelle API ASP.NET Core.

Application console, API web, Docker, Azure Functions, et tout ce qui fonctionne sous Linux ? Version de base. GDI+ ou WPF ne sont pertinents que pour une application de bureau Windows nécessitant des polices système ou un aperçu dans un contrôle natif. Sur Stack Overflow, quelqu'un a demandé si son application console avait besoin de la version WPF. La réponse était non.

Guide PDFsharp

Comment installer PDFsharp à partir de NuGet dans Visual Studio

Vous trouverez encore des messages sur les forums datant de l'époque de WinForms vous incitant à télécharger un fichier ZIP, à en extraire une DLL et à ajouter vous-même la référence. Ignorez-les. Installez PDFsharp via NuGet ; le gestionnaire de packages assure le suivi des versions, vous n'avez donc pas à vous en soucier.

  1. Ouvrez votre solution dans Visual Studio et cliquez avec le bouton droit sur le projet dans l'Explorateur de solutions.
  2. Choisissez Gérer les packages NuGet , passez à l'onglet Parcourir et recherchez « PDFsharp ».
  3. Sélectionnez PDFsharp (version de base) ou PDFsharp-MigraDoc si vous avez également besoin de la mise en page du document. Vérifiez que l'éditeur est bien empira Software GmbH.
  4. Cliquez sur Installer et acceptez l'invite de licence.
  5. Compilez le projet une fois pour confirmer que le package a été correctement restauré.

Les utilisateurs de terminaux peuvent éviter de cliquer :

bash dotnet add package PDFsharp dotnet add package PDFsharp-MigraDoc

Dans la console du gestionnaire de packages, la commande est la même : `Install-Package PDFsharp`. Et surtout, ne mélangez pas les versions. J’ai vu une équipe perdre tout un après-midi à cause de conflits de types parce qu’un projet référençait PDFsharp et que son voisin utilisait PDFsharp-GDI.

Votre premier document PDF avec PDFsharp en C

Voici le programme le plus léger permettant de générer un fichier PDF d'une seule page. Il fonctionne avec la version Core sur n'importe quel système d'exploitation, à condition qu'un gestionnaire de polices soit configuré (voir la section suivante).

```csharp
utilisation de PdfSharp.Drawing ;
utiliser PdfSharp.Pdf ;

PDFsharp 6.5+ nécessite le choix d'une licence avant la première utilisation.
PdfSharpLicense.SetAgplLicense();

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

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

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

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

Chaque programme PDFsharp suit ce schéma : document, page, XGraphics, dessin, enregistrement. Les unités sont exprimées en points (1/72 de pouce) et l’origine se situe dans le coin supérieur gauche. Sur la version 6.2.x, supprimez la ligne de licence. Cette API n’est apparue qu’à partir de la version 6.5.0.

Et la version MigraDoc :

```csharp
utilisation de MigraDoc.DocumentObjectModel ;
utilisation de MigraDoc.Rendering ;

var doc = nouveau Document();
Section section = doc.AddSection();
section.AddParagraph("Bonjour, MigraDoc !");

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

Aucune coordonnée nulle part. Ajoutez 500 paragraphes et vous obtiendrez autant de pages que nécessaire, sans aucun code de pagination de votre côté.

Polices de caractères dans la version principale de PDFsharp : le problème du résolveur

Renseignez-vous, et vous entendrez le plus souvent parler de problèmes de polices. Les versions GDI+ et WPF utilisent simplement les polices TrueType installées sous Windows. La version Core, quant à elle, ne peut rien présumer, car un conteneur Linux minimal ne dispose souvent d'aucune police utilisable. Par conséquent, le premier déploiement Docker se solde généralement par une exception indiquant qu'aucune police appropriée n'a été trouvée.

La solution consiste en un résolveur de polices, une classe qui implémente l'interface IFontResolver. Elle possède deux méthodes :

  • ResolveTypeface associe une famille et un style demandés (par exemple, « Arial », gras) à un nom de police.
  • GetFont renvoie les octets bruts du fichier TTF pour ce nom de police

Enregistrez-le une seule fois au démarrage via GlobalFontSettings.FontResolver, avant la création du premier XFont.

```csharp
classe publique 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();
```

Choses à savoir avant de les frapper soi-même :

  • Conservez vos fichiers TTF dans un dossier Fonts du projet et configurez-les pour qu'ils soient copiés dans le répertoire de sortie, ou intégrez-les en tant que ressources afin que l'image conteneur les contienne toujours.
  • La version 6.2.0 a supprimé l'ancien CoreBuildFontResolver. Sous Windows ou WSL2, il est possible de rétablir un comportement similaire avec GlobalFontSettings.UseWindowsFontsUnderWindows, mais cette méthode est sans effet sous Linux ou macOS.
  • Le dépôt d'exemples officiels inclut un SubstitutingFontResolver que vous pouvez copier comme point de départ.
  • Vérifiez la licence de la police avant de l'intégrer dans des fichiers générés. Les polices ouvertes comme Inter, Roboto ou Noto évitent complètement ce problème.

Une fois le résolveur en place, le résultat est identique sous Windows, Linux et macOS.

Fusionner, signer et sécuriser des fichiers avec PDFsharp 6

De nombreuses équipes n'ont jamais besoin de créer un document à partir de zéro. Elles utilisent la bibliothèque pour fusionner, étiqueter ou verrouiller des fichiers existants. La fusion se fait en quelques lignes : il suffit d'ouvrir chaque source en mode importation et de copier les pages.

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

Le fractionnement s'effectue en sens inverse, avec un fichier de sortie par page ou plage. Pour des raisons de sécurité, la propriété `document.SecuritySettings` requiert un mot de passe utilisateur, un mot de passe propriétaire et des indicateurs d'autorisation (impression, copie du texte, etc.).

Deux fonctionnalités très attendues ont finalement été intégrées à la version 6.2 :

  • Signatures numériques basées sur un CMS. Un signataire par défaut est fourni dans un assembly PDFsharp.Cryptography distinct ; vous pouvez intégrer le vôtre en implémentant l’interface IDigitalSigner. La prise en charge des serveurs d’horodatage fonctionne sur les versions modernes de .NET, mais pas sur la version .NET Framework.
  • Sortie PDF/A pour l'archivage. La documentation officielle indique que cette fonctionnalité présente certaines limitations et qu'elle est encore en développement ; il est donc recommandé de vérifier le résultat avec un outil de vérification PDF/A avant de s'y fier pour la conformité.

Cette version a également introduit les glyphes emoji couleur et une implémentation MD5 gérée, ce qui est important si vous travaillez sous les règles FIPS ou avec Blazor.

Dépôt PDFsharp, forks de PdfSharpCore et versions 1.x

Recherchez PDFsharp sur GitHub et vous trouverez plusieurs projets portant un nom quasi identique. La faute à l'histoire.

L'ancienne version 1.x (1.50, 1.51) ne fonctionnait que sur .NET Framework. À la sortie de .NET Core, l'attente a poussé les développeurs à la porter eux-mêmes. PdfSharpCore, initié par Stefan Steiger et repris par d'autres projets dérivés, est le plus connu. Il a supprimé GDI+ et a permis de rendre le code compatible avec Linux plusieurs années avant la sortie officielle.

Puis est arrivé PDFsharp 6 : une réécriture complète sur .NET moderne avec une version Core multiplateforme officielle. Les forks ont alors perdu la plupart de leur raison d’être.

Projet Responsable de la maintenance Plateformes Statut
PDFsharp 6.x (dépôt empira/PDFsharp) empira Software GmbH .NET 8–10, .NET Standard 2.0, .NET Framework 4.6.2 Maintien actif
PDFsharp 1.5x empira Software GmbH .NET Framework uniquement Le code source est conservé sur GitHub, mais n'est plus maintenu.
PdfSharpCore et ses dérivés Communauté .NET Core / .NET Standard 2.0 Varie selon la version, mises à jour plus lentes
PDFsharp-MigraDoc 6.x empira Software GmbH Identique à PDFsharp 6 Maintien actif

Alors, ce débat récurrent sur « PdfSharp vs PdfSharpCore » sur Reddit ? Nouveau projet, packages officiels. Ne conservez un fork que si votre ancien code en dépend déjà et que la migration ne justifie pas un sprint de développement pour le moment. Et si la documentation vous semble insuffisante, consultez le dépôt d'exemples d'Empira. Ses dossiers et fichiers contiennent des exemples exécutables, bien plus pratiques que de deviner.

PDFsharp est-il gratuit ? Changements de licence dans PDFsharp 6.5

Pendant la majeure partie de son existence, oui. Il était sous licence MIT, ce qui signifie une utilisation commerciale quasiment sans restrictions. Toutes les versions jusqu'à la 6.2.4 incluse le sont encore.

La version 6.5.0 a changé cela. La bibliothèque est désormais sous double licence :

  • Licence AGPL (gratuite). Vous pouvez l'activer en appelant `PdfSharpLicense.SetAgplLicense()` avant d'utiliser la bibliothèque. La licence AGPL vous oblige à rendre votre code source accessible aux utilisateurs, y compris ceux qui interagissent avec votre logiciel via un réseau ; elle est donc peu adaptée aux solutions SaaS à code source fermé.
  • Licence commerciale. Vous achetez une clé de licence auprès du fournisseur et l'utilisez avec PdfSharpLicense.LoadLicense(...). Cela vous libère des obligations liées à l'AGPL.

À partir de la version 6.5.0, votre code doit en choisir une explicitement. Les versions préliminaires de la version 7.0 fonctionnent de la même manière.

En pratique:

  • Les projets open source compatibles avec l'AGPL peuvent continuer à utiliser gratuitement la version la plus récente.
  • Les logiciels propriétaires peuvent soit acheter une licence commerciale, soit rester sur la version 6.2.x, qui demeure sous licence MIT. Rester sur cette version signifie ne pas bénéficier des correctifs futurs ; il est donc important d’en évaluer honnêtement le coût.
  • Quel que soit votre choix, lisez attentivement le texte intégral de la licence et faites-le approuver par votre service juridique. Ce guide ne constitue pas un avis juridique.

Guide PDFsharp

Points faibles de PDFsharp et outils à privilégier

La bibliothèque remplit bien sa fonction. Son champ d'application est simplement limité, et les mêmes lacunes reviennent systématiquement dans les discussions de forum.

  • PDFsharp ne prend pas en charge la conversion HTML vers PDF. Il n'interprète ni HTML ni CSS. Un module complémentaire communautaire, HtmlRenderer.PdfSharp, existe, mais il ne prend en charge que HTML 4.01 et CSS niveau 2 ; les mises en page modernes avec Flexbox ou Grid ne sont donc pas compatibles. Les équipes qui ont besoin de modèles HTML optent généralement pour un moteur de rendu sans interface graphique.
  • JavaScript non autorisé. Les graphiques et le contenu générés côté client ne peuvent pas être capturés.
  • PDFsharp ne prend pas en charge le rendu d'images. Il ne permet pas de convertir une page PDF en PNG pour les vignettes ou les aperçus. Un logiciel de rastérisation externe est nécessaire.
  • Extraction de texte limitée. Il est possible de parcourir le flux de contenu, mais aucune API de haut niveau ne permet de récupérer un texte propre avec les positions. PdfPig, une bibliothèque open source distincte, est conçue spécifiquement pour la lecture et l'extraction de texte.
  • Prise en charge partielle des formulaires. Le remplissage simple des formulaires AcroForm fonctionne ; les formulaires complexes avec scripts, c’est une autre histoire.
  • Les tableaux nécessitent MigraDoc. Avec PDFsharp standard, vous calculez vous-même la hauteur de chaque ligne.

Cela n'en fait pas pour autant un mauvais choix. Les documents basés sur des données, comme les factures, les relevés, les étiquettes et les certificats, sont son point fort, et son encombrement est minime. En revanche, les copies parfaites de pages web ne le sont pas.

PDFsharp pour les factures et les reçus de paiement en cryptomonnaie

Les reçus sont probablement le document le plus fréquemment créé avec PDFsharp. Les reçus de cryptomonnaies sont un peu plus complexes que ceux des cartes bancaires. Bonne nouvelle : dès que la passerelle de paiement déclenche votre webhook (une notification HTTP envoyée lorsque le statut du paiement change), vous disposez de toutes les données. Aucune autre recherche n'est nécessaire.

Ce que j'y mettrais :

  • Numéro de commande ou de facture et coordonnées du commerçant
  • Montant en cryptomonnaie et son équivalent en monnaie fiduciaire au moment du paiement
  • Pièce et réseau (par exemple, USDT sur TRON contre USDT sur Ethereum)
  • Hachage de la transaction, permettant au client de la vérifier sur un explorateur de blocs.
  • Une adresse de portefeuille de réception raccourcie et le délai de confirmation
  • Un code QR renvoyant à la page de transaction ou de facture

Utilisez une police à chasse fixe pour les dièses et les adresses. Les clients les lisent caractère par caractère, et en Arial, un zéro et un O majuscule se ressemblent beaucoup. Si le dièse est trop large, passez à la ligne ; une police de 6 points n’est lisible par tous. Incorporez les polices, enregistrez le fichier avec la commande et signez-le si votre comptable vous demande un reçu.

Tout ceci ne concerne pas l'encaissement. Pour cela, vous utiliseriez une passerelle comme Plisio . Celle-ci accepte le BTC, l'USDT et de nombreuses autres cryptomonnaies, génère la facture et appelle votre point de terminaison à chaque changement de statut. Votre gestionnaire transmet ensuite les données à MigraDoc et l'acheteur reçoit un reçu avec votre logo directement sur la page de remerciement.

Conclusion

Je reviens toujours à PDFsharp pour une raison simple : il est léger et discret. La version Core fonctionne partout où .NET est compatible, et MigraDoc prend en charge la mise en page lorsqu'un simple canevas ne suffit pas. Trois points sont à régler rapidement : la version à utiliser, le mode de chargement des polices et la licence (la version 6.5 étant désormais sous licence AGPL). Imprimez des données, pas des pages web, et votre logiciel fonctionnera pendant des années.

Des questions?

Générer des PDF à partir de code .NET, principalement : factures, rapports, étiquettes d’expédition, certificats… C’est également pratique pour fusionner et diviser des fichiers, ou ajouter des numéros de page et des filigranes à des PDF créés par d’autres. Avec MigraDoc, même les longs documents contenant des tableaux et des graphiques deviennent un jeu d’enfant.

Jusqu’à la version 6.2.4, oui, elle est sous licence MIT et vous pouvez l’intégrer à des produits payants. À partir de la version 6.5.0, deux options s’offrent à vous : la licence AGPL est gratuite mais vous oblige à partager votre code source ; la licence commerciale est payante et ne vous y oblige pas. Votre code source doit préciser laquelle choisir.

Non. Il n’y a pas de moteur HTML ou CSS intégré. Un module complémentaire communautaire appelé HtmlRenderer.PdfSharp tente de le faire, mais il se limite à HTML 4.01 et CSS 2 ; par conséquent, tout ce qui utilise Flexbox ou Grid est incompatible. Pour les pages web réelles, on utilise un convertisseur fonctionnant sur un navigateur sans interface graphique.

Via NuGet. Dans Visual Studio, faites un clic droit sur le projet, sélectionnez « Gérer les packages NuGet », puis recherchez « PDFsharp ». Dans un terminal, la commande `dotnet add package PDFsharp` suffit. Vous souhaitez également ajouter des tableaux et la pagination ? Ajoutez PDFsharp-MigraDoc. Plus besoin de copier les DLL manuellement.

Pour les mises en page fixes et les modifications de fichiers existants : PDFsharp. Pour tout ce qui implique du texte continu, des tableaux qui s’agrandissent et des coupures de page intempestives : MigraDoc. Honnêtement, vous finirez probablement par utiliser les deux, et comme MigraDoc s’appuie sur PDFsharp, ils fonctionnent parfaitement ensemble.

PDFsharp 6 est compatible avec .NET 8, 9 et 10, ainsi qu’avec .NET Standard 2.0 et .NET Framework 4.6.2. La version Core fonctionne sous Windows, Linux et macOS. Les versions GDI+ et WPF sont compatibles uniquement avec Windows. Vous utilisez Linux ? Configurez d’abord un gestionnaire de polices pour éviter les erreurs de police.

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.