PDFs in der Cloud erstellen – Unser Lösungsansatz
In Sachen PDF-Generierung wollten wir uns nicht an einen Hersteller binden. Die Auswahl an OpenSource Software zur PDF Erstellung ist jedoch nicht gerade bunt und jede Lösung hat so ihre Schwächen. Die API von OpenOffice im Headless Modus ist im Funktionsumfang eingeschränkt, die Skalierung nur schwer realisierbar. Andere Lösungen, wie PDF Generierung über eine Headless Chrome Instanz, wie es viele NodeJS Bibliotheken verwenden, scheitern oft an der Dokumentbeschreibung über HTML. Definierte Regeln für Seitenumbrüche, automatische Seitenzahlen und Inhaltsverzeichnisse verlieren oft erst auf den zweiten Blick ihren trivialen Schein.
Als gute Möglichkeit den Aufbau von Dokumenten zu beschreiben hat sich ein altbewährtes Mittel hervorgetan – LaTeX. Anders als es der Name vermuten lässt, ist es der Standard zum Schreiben wissenschaftlicher Arbeiten, vor allem in technischen Studiengängen. Der erste Vorteil liegt daher auf der Hand, die meisten Programmierer mit akademischen Hintergrund können Vorlagen bearbeiten und erstellen. LaTeX hat aber einen weiteren großen Vorteil. LaTeX-Files sind textbasierte Dateien und können über die Kommandozeile zu einem PDF kompiliert werden. Dies haben wir uns zu Nutze gemacht und daraus ein skalierbares Cloud-System entwickelt.
Architektur Überblick
In folgender Grafik ist der Aufbau unseres Systems dargestellt. Anschließend wird auf diesen Aufbau näher eingegangen:
Ablauf
1. Der Admin erstellt ein oder mehrere LaTeX-Templates in einem Git-Repository
2. Optional: Der Admin kann ein Template versionieren
3. Der Benutzer schickt eine Anfrage von seinem Browser/App zu dem LaTeX-Service und gibt das gewünschte Template an
4. Benutzerdaten werden im Template ersetzt
5. Der Benutzer kann das fertige PDF herunterladen (Downloadlink von Firebase Storage)
PDF Erstellung im Docker Container
Wie in der Einleitung angesprochen, können die LaTeX-Files via Kommandozeile zu einem PDF kompiliert werden. Diesen Mechanismus haben wir in einen Docker Container gepackt. Zusätzlich haben wir den “LaTeX Compiler” noch erweitert. Vor dem Kompilierungsvorgang werden die LaTeX-Files durch den Text-Replacer geschickt. Im LaTeX-Template können somit einzelne Keys festgelegt werden, die durch einen benutzerdefinierten Text ersetzt werden. Ähnlich können auch SVGs oder andere Bilder ersetzt und eingefügt werden. Angesprochen wird der Service über REST.
Templates im Git-Repository
Alle Templates werden in einem Git-Repository eingecheckt. Als Hosting Dienst verwenden wir GitHub, alternativ wäre aber jeder beliebige Git-Server möglich. Jedes Template liegt in einem eigenen Ordner und beinhaltet alle nötigen Dateien (LaTeX-File, statische Bilder etc.).
Versionierung
Die Templates können einzeln als Version für den LaTeX-Service bereitgestellt werden. Folgende REST Anfrage löst einen Upload zu Firebase aus. Alle Dateien werden in Firebase unter `templates/myTemplate/V1/` zur Vergügung gestellt:
GET /newVersion?template=myTemplate
Der Name des Templates ist immer der jeweilige Ordnername im Git-Reposiory.
Benutzeranfrage zur PDF Generierung
Der Benutzer bzw. die Applikation kann mit folgender Anfrage die PDF Generierung auslösen:
Der LaTeX Serivce im Docker Container lädt sich nun die entsprechende Template-Version von Firebase herunter und ersetzt den Text und die Bilder mit den mitgegebenen Keys. Die Keys können im LaTeX-File vorher entsprechen definiert werden.
Sobald der LaTeX-Compiler fertig ist, lädt er das erstellte PDF in den Firebase Storage und gibt den Downloadlink an den Benutzer zurück. Der Benutzer hat nun die Möglichkeit das PDF gleich oder zu einem späteren Zeitpunkt herunterzuladen.
Dynamische Diagramme mit SVG und ReCharts
Um in den PDFs neben Bildern auch dynamisch erstellte Diagramme einzubinden, rendern wir zunächst die Diagramme im Browser/App. Dazu verwenden wir React mit der Bibliothek [recharts](https://github.com/recharts/recharts). Um ein entsprechendes Diagramm in ein SVG zu speichern sind nur folgende 3 Codezeilen nötig:
Dieses svgBlob wird nun als svgKey an unseren LaTeX-Service geschickt und in das PDF eingebunden. Dadurch können wir im PDF die selben Diagramme einfügen, wie sie auch auf der Website dargestellt werden.
Betrieb und Skalierung
Da der LaTeX-Service in einem Docker Container läuft, war es recht einfach, ihn in den bestehenden Kubernetes Cluster einzubinden. Die Skalierung wird durch eine simple Erhöhung der Instanzen oder der Zuweisung von mehr Rechenleistung bewerkstelligt. Der Kubernetes Cluster läuft derzeit auf der Google Cloud Platform, weshalb wir für dieses Projekt auch Firebase Storage gewählt haben. Als Alternative zum Firebase Storage könnte man z.B. auch AWS S3 verwenden.