Retour

Utilisation de l’API Gotenberg pour la génération PDF

Migration technologique : de wkhtmltopdf vers Gotenberg

La génération PDF est devenue un enjeu critique dans bon nombre de projets développés par Digital Garden. Pendant longtemps, notre stack technique s’appuyait sur l’outil open source wkhtmltopdf, reconnu pour sa capacité à convertir des pages HTML/CSS en PDF via le moteur WebKit. Toutefois, ce projet a été officiellement archivé en 2023, posant un problème de maintenance et de compatibilité à long terme.

Dans une logique de continuité de service, de sécurité et de performance, nous avons choisi de migrer vers Gotenberg, une solution moderne et robuste. Il s’agit d’une API en container Docker permettant la conversion de documents (HTML, Markdown, Office...) en PDF, s’intégrant parfaitement dans une architecture microservices. Ce choix technologique offre :

  • Une meilleure interopérabilité avec les systèmes backend modernes,
  • Un déploiement sécurisé et scalable sur nos environnements Docker mutualisés ou dédiés,
  • Une qualité de rendu supérieure avec un meilleur support des standards HTML5 et CSS3,
  • Et surtout, une pérennité grâce à une communauté active et des mises à jour régulières.

Cette évolution s’inscrit dans notre démarche globale d’amélioration continue et de modernisation des socles techniques utilisés pour accompagner nos clients dans leurs projets à forte valeur ajoutée.

Gotenberg : une API de conversion PDF

 

Gotenberg est donc une API de génération PDF indépendante, permettant d’envoyer un document HTML, une url ou encore un fichier libreoffice pour qu’elle nous retourne le binaire d’un PDF.

Dans le cas de Digital Garden, 2points d’entrées sont intéressant :

 

  • POST /forms/chromium/convert/html :permettant de transformer un fichier HTML en PDF.
  • POST /forms/libreoffice/convert : qui va nous permettre de merger deux documents entre eux.

 

Cela change l’architecture de ce que nous avions avec wkhtmltopdf. Alors qu’auparavant chaque projet avait son propre générateur de pdf :

Appel unitaire du binaire wkhtmltopdf

A présent nous allons appeler une API Gotenberg mutualisé :

Appel d'un micro service Gotenberg

Tableau comparatif wkhtmltopdf vs Gotenberg

wkhtmltopdf

Avantages

  • Gestion précise des versions par projet
  • Possibilité de gérer la mémoire allouée par  projet.

Inconvénients

  • Disparité de rendu possible selon les projets
  • Démultiplication inutile des ressources pour  la même tâche
  • Maintenance compliquée (plusieurs  versions/processus à maintenir)
  • N’est  plus maintenu

Gotenberg

Avantages

  • Ressources mutualisées pour l’intégralité desprojets.
  • Possibilité de scalabilité car dans un serviceséparé
  • Toujours maintenu
  • Possibilité de mutualisation du code plus poussée (Bundle commun)

Inconvénients

  • Même version pour tous les projets.
  • Même gestion de la mémoire pour tous les projets (adaptation nécessaire si un projet a besoin de générer un énorme PDF d’un coup).

Installation de l’API Gotenberg

L’installation de l’API Gotenberg se fait très simplement grâce à docker-compose, le service ayant déjà son image docker complète :

// compose.yaml
services:
  gotenberg:
    image: gotenberg/gotenberg:8  // Nous avons fixé à la version 8, libre à vous d’en utiliser une autre.
    command: gotenberg –api-port=80 –api-timeout=60s
    ports:
      - "10080:80"

Notez la présence de la propriété command qui nous permet de changer la commande par défaut lancée par le container. Ici gotenberg avec les options suivantes :

  • api-port permettant de spécifier le port utilisé par l’API à l’intérieur du container. Ici la redirection est faite vers le port 10080 de l’hôte par le paramètre ports.
  • api-timeout permettant de régler le temps maximum de réponse de l’API. Cette option est utile si vous avez de gros PDF à générer.

Ainsi, en allant sur https://localhost:10080 vous devriez voir un lien vers la documentation de Gotenberg. Félicitations, l’API est fonctionnelle.

Intégration de Gotenberg

Pourintégrer Gotenberg à votre application, il existe déjà un bundle créé parSensiolabs, sensiolabs/gotenberg-bundle, quifournit les services utiles pour vous interfacer avec l’API. Cependant, cesservices peuvent être complexes à utiliser (distinction des screenshot et desgénérateurs, envoi des assets liés aux pdf, etc.)

 

Nousavons donc créé un autre bundle, dgarden/gotenberg-bundle, utilisant lebundle de Sensiolabs, qui donne accès directement aux fonctionnalitéssuivantes :

  •  Un service DigitalGarden\GotenbergBundle\Generator\PdfFileGenerator ayant des helpers simples pour réaliser les opérations communes de génération de PDF :

◦        html() :Permettant de générer un PDF à partir d’un code HTML.

◦        htmlFile() :Permettant de générer un PDF à partir d’un fichier HTML.

◦        merge() : Permettant de fusionner 2 PDF.

◦        mergeWithOptions() :Identique à merge, mais permettant de mettre des options (attention à l’ordre des paramètres, les options sont en premier).

◦        template() : Permet de générer à partir d’un template Twig.

◦        url() :Permet de générer à partir d’une url.

  •   Des commandes pour générer en console vos PDF:

◦        dgarden:pdf:html : Génération d’un PDF à partir d’un fichier html ou de code html.

◦        dgarden:pdf:merge : Fusion de plusieurs PDF.

◦        dgarden:pdf:template : Génération d’un PDF à partir d’un template.

◦        dgarden:pdf:url : Génération d’un PDF à partir d’une url.

  • Une gestion de la génération asynchrone (Voir le chapitre : Génération synchrone VS asynchrone).

D’autres fonctionnalités sont prévues et peut-être déjà implémentés, n’hésitez pas à jeter un coup d’œil aux fichiers TODO.md etCHANGELOG.md dans le repository du projet.

Pour installer le bundle, il vous suffit de lancer la commande :

composer require dgarden/gotenberg-bundle

Génération synchrone vsasynchrone

 

Comme le suggère l’option api-timeout, la génération du PDF peut prendre un certain temps. C’est pourquoi Gotenberg implémente une génération asynchrone :

Génération synchrone

Génération asynchrone

Le bundle dgarden/gotenberg-bundle contient déjàtout ce qui est nécessaire pour traiter cette génération asynchrone. Ainsi si vous donnez l’option DigitalGarden\GotenbergBundle\Generator\PdfFileGeneratorOptions::OPTION_ASYNC à vos générations (--async pour les commandes), l’API Gotenberg vous répondra immédiatement, et enverra une requête sur la route ‘/_dg/pdf/generate’ (déjà configurée dans votre router par le bundle).

Par défaut, le bundle va enregistrer les PDF dans le répertoire ‘%kernel.project_dir%/var/pdf’ (modifiable par le paramètre de configuration dgarden.gotenberg.output_path), vous pouvez cependant intercepter ou modifier ce comportement grâce à l’évènement DigitalGarden\GotenbergBundle\Event\PdfGeneratedEvent.

Conclusion

Le projet wkhtmltopdf peut simplement être remplacé par Gotenberg, pouvant ainsi mutualiser la génération des PDF à travers tous nos projets sur une architecture micro-service. De notre expérience, les PDF ainsi générés sont très similaires à ceux générés par wkhtmltopdf, et nous n’avons pas eu à faire de gros changements sur les templates / code de nos applications.

Allez plus loin

Chez Digital Garden, nous avons l’habitude de concevoir et mettre en œuvre des solutions de génération dynamique de fichiers PDF. Ce savoir-faire s’applique aussi bien à des cas d’usage B2B qu’à des dispositifs à forte dimension B2C :

  • Pour Socopa, nous avons conçu une plateforme commerciale dotée d’un générateur de fiches produits PDF, destinées aux équipes de vente sur le terrain.
  • Chez Bridor, les utilisateurs professionnels peuvent configurer et éditer des fiches techniques produits en PDF, personnalisées selon leurs critères de sélection.
  • Pour Definox, les catalogues personnalités avec les tarifs spécifiques à chaque client est généré grâce à cette librairie.
  • En B2C, nous avons développé des devis interactifs ou encore des rapports PDF issus de configurateurs avancés (produits, abonnements, services...), permettant une restitution immédiate et valorisante de l’offre au client.

Hésitez pas à nous contacter si vous avez des problématiques de personnalisation de PDF.

D’autres articles à découvrir