Entwickler von Websites und mobilen Anwendungen müssen häufig die Vorbereitung von PDF-Seiten zum Drucken oder zum Versenden per E-Mail an Kunden steuern.
PDF-Dateien haben die volle Kontrolle über die Anzeige von Text und Grafiken auf der Seite. Leider sind Bibliotheken zum Generieren von dynamisch aufgefüllten PDF-Dateien nicht in den Standardtools von PHP, JS (Web), Java oder Swift (Android bzw. iOS) enthalten. In diesem Artikel möchte ich Sie über die Open Source-Lösung zum Generieren von PDF-Dateien informieren.
JasperReports ist eine Open-Source-Java-Bibliothek zum Generieren dynamisch aufgefüllter Dateien. Es verfügt über viele Tools zum Erstellen komplexer Berichtsformulare, auch im PDF-Format. Es stehen jedoch auch andere Formate zur Verfügung: RTF, DOCX, HTML, XLS, XLS, CSV und XML. Mit anderen Worten, es reicht aus, ein Formular zu entwickeln, ein Layout zu erstellen - und es wird möglich sein, es in eines der oben genannten Formate zu exportieren.
Es gibt auch gute Bibliotheken wie PDFLib (kommerzielle Version) für PHP und die Open Source-Version von PDFLib-Lite. Die Bibliothek ist zwar recht teuer, und die Lite-Version wird nur im Quellcode verteilt. Wenn sie in der Entwicklungsumgebung installiert wird, kann diese Einschränkung zu einem Problem werden.
PDFbox ist eine weitere Open-Source-Java-Bibliothek für die Arbeit mit PDF-Dokumenten. Sie können neue PDF-Dokumente erstellen, vorhandene Dokumente verwalten und Inhalte daraus extrahieren. Im Gegensatz zu JasperReports verfügt es jedoch nicht über eine Benutzeroberfläche.
Ich denke, JasperReports ist besonders nützlich in großen Projekten im Zusammenhang mit der Berichterstellung und nicht nur im PDF-Format. Es bietet alles, was Sie zur Implementierung in Ihrem Projekt benötigen: einfache Erstellung komplexer Berichtsformulare, Benutzeroberfläche für komfortables Layout, Serveranwendung und einfache Integration in die Front.
In dem Artikel werde ich folgende Themen behandeln:
- Installieren Sie die Entwicklungsumgebung und die Serveranwendung.
- Erstellen Sie eine PDF-Datei, die automatisch aus der Datenbank ausgefüllt wird.
- Integration der Serveranwendung in das Frontend, um das erstellte PDF zu erhalten.
Um JasperReports in Ihrem Projekt verwenden zu können, müssen Sie zwei Anwendungen herunterladen: JaspersoftStudio - im Folgenden als
Arbeitsumgebung bezeichnet - und JasperServer - als
Serveranwendung .
JaspersoftStudio ist eine Eclipse-basierte Entwicklungsumgebung mit der integrierten JasperReports-Java-Bibliothek, in der dynamische oder statische PDF-Dateien entwickelt werden: z. B. Tickets, Quittungen, Verträge, Analysediagramme und andere.
JasperServer ist eine Serveranwendung, in der Dateien von JaspersoftStudio bereitgestellt und gespeichert werden. Sie können von einer mobilen oder Webanwendung aus aufgerufen werden. JasperServer verfügt über eine Benutzeroberfläche, mit der Sie Berichte anzeigen, Konten für verschiedene Benutzer erstellen und ihnen entsprechenden Zugriff gewähren können. Sie können die Mailingliste auch für E-Mail konfigurieren (Scheduler).
Richten Sie die Arbeitsumgebung und die Serveranwendung ein
Sie können Anwendungen über die obigen Links herunterladen und installieren. Nach dem Einrichten von zwei Anwendungen muss eine Verbindung von der Arbeitsumgebung zur Serveranwendung hergestellt werden.
Server → JasperReports- Serververbindung
erstellen → Geben Sie den bevorzugten Servernamen, die
URL , den Benutzernamen und das Kennwort an. Klicken Sie auf Verbindung
testen , um zu überprüfen, ob die Verbindung zum Server hergestellt wurde. Wenn Sie
Erfolg sehen, gehen Sie weiter.

Erstellen Sie ein dynamisch ausgefülltes PDF und veröffentlichen Sie es
Wir haben die Entwicklungsumgebung und den Server installiert und eine Verbindung zwischen ihnen hergestellt. Erstellen wir nun eine primitive, dynamisch aufgefüllte PDF-Datei, die beim Start (generiert) Daten aus PostgreSQL entnimmt und auf einer Serveranwendung installiert.
Zunächst sollten Sie die Datenquelle (in unserem Fall PostgreSQL) an die Arbeitsumgebung anschließen, von wo aus das PDF die Daten übernimmt. Dann beginnen wir mit der Entwicklung unserer ersten PDF-Datei.
Datenadapter → Datenadapter erstellen → Datenbank-JDBS-Verbindung und geben Sie die Verbindungsdaten an:
- JDBC-Treiber - PostgreSQL (org.postgresql.Driver). Wenn für Ihr DBMS kein Treiber vorhanden ist, können Sie den erforderlichen Treiber auf der Registerkarte Treiberklassenpfad installieren.
- JDBC-URL - besteht aus ihrem Host-, Port- und Datenbanknamen.
- Benutzername und Passwort - Protokollausweis von Ihrem DBMS-Konto.

Wir klicken auf die uns bereits vertraute Schaltfläche
Test und nach erfolgreicher Verbindung (Erfolgreich) mit der Datenbank -
Fertig stellen .
Aus dieser Datenbank wird das PDF in die Produktionsumgebung eingefügt. Da wir planen, unsere erste PDF-Datei auch auf dem Server bereitzustellen, schrauben wir dieselbe Datenquelle in die Serveranwendung:
Datenquellen → Ressource hinzufügen → Datenquelle und wiederholen Sie alles ab dem obigen Punkt.
Jetzt können Sie das PDF erstellen. Quellen in JasperReports werden im JRXML-Format gespeichert - dies ist XML mit verkabelten Tags und Attributen, mit denen die JasperReports-API arbeitet.
Klicken Sie auf
Datei → Neu → Jasper-Bericht → Leer A4 → Geben Sie den Namen der JRXML-Datei an → Fertig stellen .

Nach dem Erstellen eines neuen Projekts sehen Sie das folgende Bild:

Sieben verschiedene Blöcke - jeder Block hat sein eigenes Verhalten, das sich von den anderen unterscheidet. Weitere Informationen hierzu finden Sie in der
Dokumentation . Wenn Sie auf Quelle klicken, sehen Sie die Struktur dieser Blöcke:
<?xml version="1.0" encoding="UTF-8"?> <jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="Example" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="ae9517f6-ff0b-41bb-a8dc-82196190e940"> <queryString> <![CDATA[]]> </queryString> <background> <band splitType="Stretch"/> </background> <title> <band height="79" splitType="Stretch"/> </title> <pageHeader> <band height="35" splitType="Stretch"/> </pageHeader> <columnHeader> <band height="61" splitType="Stretch"/> </columnHeader> <detail> <band height="125" splitType="Stretch"/> </detail> <columnFooter> <band height="45" splitType="Stretch"/> </columnFooter> <pageFooter> <band height="54" splitType="Stretch"/> </pageFooter> <summary> <band height="42" splitType="Stretch"/> </summary> </jasperReport>
Entfernen wir also fünf zusätzliche Blöcke und lassen nur zwei übrig: Titel und Detail. Die Schaltfläche
Löschen (Windows) oder die
Rücktaste (OS X) helfen uns dabei.
Fügen Sie nun zwei Elemente hinzu. Sie können ein neues Element auf zwei Arten hinzufügen: Registrieren Sie den Container in der XML-Struktur (Schaltfläche
Quelle ) oder ziehen Sie das gewünschte Element aus dem oberen rechten
Palettenfenster - Statischer Text, in dem Feldnamen und Textfelder enthalten sind, in die die aus der Datenbank gezogenen Variablenfelder eingetragen werden:
<?xml version="1.0" encoding="UTF-8"?> <jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="Example" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="ae9517f6-ff0b-41bb-a8dc-82196190e940"> <queryString> <![CDATA[]]> </queryString> <background> <band splitType="Stretch"/> </background> <title> <band height="30" splitType="Stretch"> <staticText> <reportElement x="0" y="0" width="100" height="30" uuid="7b697ed9-f52a-483c-965e-f0b2dc6130c1"/> <text> <![CDATA[Static Text]]> </text> </staticText> </band> </title> <detail> <band height="169" splitType="Stretch"> <textField> <reportElement x="0" y="0" width="100" height="20" uuid="41002e0b-ddb2-4e4b-a049-10810ab51208"/> <textFieldExpression> <![CDATA["Text Field"]]> </textFieldExpression> </textField> </band> </detail> </jasperReport>
Die Abfrage in der Datenbank kann in das
queryString- Tag geschrieben werden oder Sie klicken auf die
Dialogschaltfläche DataSet und Query Editor . Danach öffnet sich ein neues Fenster, in dem Sie eine Datenquelle (1) auswählen, eine Abfrage (2) schreiben und Feldvariablen deklarieren müssen. Die Schaltfläche Felder lesen (3) liest auf
gültige Anfrage automatisch alle Felder. Klicken Sie zum Anzeigen der Daten auf Datenvorschau (4).

Großartig! Wir haben vier Felder vom Typ String, jetzt können wir fast jede Manipulation mit ihnen durchführen. Zum Beispiel listen wir sie einfach auf und schreiben eine kleine Logik.
Wir drucken die Namen der erforderlichen Felder in die statischen Textelemente und platzieren sie im Titelcontainer. Wir werden variable Felder in den Textfeldelementen im Detailcontainer angeben, da sie sich multiplizieren. In unserem PDF werden Name, Stadt und E-Mail-Adresse angezeigt. Um nicht völlig gelangweilt zu sein, schreiben wir eine einfache Logik in das Textfeldelement, wobei wir das vierte Feld verwenden - das Geschlecht des Kunden, Geschlecht.
Wir machen Folgendes: Wenn der Kunde eine Frau ist, wird Frau vor dem Namen hinzugefügt, wenn der Mann Herr ist. Verwenden Sie dazu den ternären Java-Operator:
<textFieldExpression> <![CDATA[$F{sex}.equals( "male" )?"Mr. "+$F{name}:"Mrs. "+$F{name}]]> </textFieldExpression>
Wenn Sie neben der Schaltfläche
Quelle auf
Vorschau klicken, sehen Sie das Ergebnis:

Wie Sie auf dem Screenshot sehen können, wurde das PDF erfolgreich zusammengestellt: Es hat alle Werte übernommen und die Logik angewendet, wobei Mrs. und Mr.
Wir erhalten auch den City-Eingabeparameter, damit Daten nach Stadt gefiltert werden können. Dies kann entweder durch Klicken auf
Parameter → Parameter erstellen im Gliederungsfenster oder durch Hinzufügen eines neuen
Parameter- Tags mit den
Namen- und
Klassenattributen erfolgen :
<parameter name="City" class="java.lang.String"/>
Es bleibt nur der Parameter zur SQL-Abfrage hinzuzufügen:
SELECT Id, name, sex, city, email FROM users WHERE city = $P{City}
Wir übergeben den Wert San Francisco an den City-Parameter (ich werde Ihnen im nächsten Absatz erklären, wie das geht) und klicken auf
Datenvorschau , um das Ergebnis anzuzeigen.
Das PDF wurde durch erfolgreiches Filtern der Daten gesammelt. Wir gehen weiterDa wir bereits eine dynamisch füllende PDF-Datei haben, können wir diese zur weiteren Integration in unsere Front-End-Anwendungen auf den Server hochladen. Klicken Sie dazu auf die Schaltfläche
Bericht auf JasperReports Server veröffentlichen → Doppelklicken Sie, um den Server zu öffnen → Wählen Sie den Serverordner aus, in den die PDF-Datei heruntergeladen werden soll (in unserem Fall
Berichte ) →
Weiter → Datenquelle aus dem Repository → Wählen Sie die Datenquelle aus, die zuvor in der Serveranwendung erstellt wurde →
Fertig stellen .
Frontend-Integration
Die JasperReports-API enthält eine eigene RESTful-Implementierung für die Client-Server-Interaktion -
REST v2 . Wenn es Ihnen nicht passt, können Sie ein einfaches Objektzugriffsprotokoll verwenden -
SOAP .
Wir werden REST v2 betrachten.
Die vier Hauptmethoden für CRUD-Aktionen (Create-Read-Update-Delete) stehen zur Verfügung: GET (Get), POST (Hinzufügen, Ändern, Löschen), PUT (Hinzufügen, Ersetzen), DELETE (Löschen). Alle detaillierten Informationen finden Sie in der Dokumentation unter den obigen Links.
Wir werden die allgemeinere und relevantere GET-Methode für diesen Artikel betrachten.
http://<host>:<port>/jasperserver[pro]/rest_v2/reports/path/to/report.<format>?<arguments>
Oben sehen Sie eine
synchrone Anfrage, mit der Sie die Ausgabe der Datei (fertiges PDF) in einer Anfrage-Antwort erhalten können (den asynchronen Aufruf finden Sie
hier ).
Ich denke, mit dem Host und dem Port ist alles klar, und
/ reports / path / to / report ist der URI der Datei, die aufgerufen wird. Da wir die Quelle der PDF-Datei (Example.jrxml) im Berichtsserverordner bereitgestellt haben, lautet die ausgefüllte URI-Option: / reports / reports / Example.
Format ist ein Format (in unserem Fall PDF).
Argumente sind Parameter.
Oben haben wir den Parameter "Stadt" hinzugefügt und übergeben ihn in der Anforderung mit dem Wert "San Francisco", um Daten für diese Stadt zu filtern.
Wenn der Anruf nicht aus einer autorisierten Zone stammt, müssen Sie zwei weitere Parameter / Attribute hinzufügen:
j_username und
j_password (Protokollpass für die Autorisierung). Standardmäßig lautet der Benutzername und das Kennwort auf dem Server
jasperadmin .
Somit erhalten wir folgende URL:
http://localhost:8080/jasperserver/rest_v2/reports/reports/Example.PDF?city=San Francisco&j_username=jasperadmin&j_password=jasperadmin
So erhalten wir ein bereits generiertes PDF. Wenn Sie diese URL beispielsweise über die Adressleiste des Browsers aufrufen, sollte die Datei automatisch heruntergeladen werden.
Möglicherweise müssen Sie ein PDF-Bild anzeigen. Wenn der Client beispielsweise nur die Datei anzeigen möchte, können Sie das Dokument im PNG-Format anzeigen, wenn Sie es herunterladen möchten, dann als PDF.
Am Beispiel von Java anhand der PDFbox-Bibliothek wird untersucht, wie Sie eine PDF-Datei aus einer externen Anwendung generieren, auswählen und anschließend in PNG konvertieren können.
Unten finden Sie die
PullPDF- Klasse mit einer Methode, die eine URL als Argument verwendet.
import java.awt.image.BufferedImage; import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.net.URL; import java.util.Base64; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.rendering.ImageType; import org.apache.pdfbox.rendering.PDFRenderer; import org.apache.pdfbox.tools.imageio.ImageIOUtil; public class PullPDF { public String ConvertPDF2PNG(String valuefromParam) throws IOException { BufferedInputStream input_file = new BufferedInputStream(new URL(valuefromParam).openStream()); ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { PDDocument document = PDDocument.load(input_file); PDFRenderer pdfRenderer = new PDFRenderer(document); for (int page = 0; page < document.getNumberOfPages(); ++page) { BufferedImage bim = pdfRenderer.renderImageWithDPI(page, 300, ImageType.RGB); ImageIOUtil.writeImage(bim, "png", baos); baos.flush(); byte[] encodedBytes = Base64.getEncoder().encode(baos.toByteArray()); valuefromParam = new String(encodedBytes); } } catch (Exception e) { } return valuefromParam; } }
Sie können das gleiche Ergebnis beispielsweise mit dem Spring Framework erzielen. Aber ich habe versucht, einen universellen Weg aufzuzeigen, der sowohl auf Android als auch auf das Web angewendet werden kann, wenn mit Java gearbeitet wird.
Fazit
Wenn Sie die Generierung einer einfachen Prüfung für einen Online-Shop automatisieren möchten und nur begrenzte Zeit zum Erstellen haben, empfehle ich die Verwendung der nativen Tools Ihres Projekts oder des bekannten Frameworks. Aufgrund des Zeitaufwands für die Installation von JasperReports ist es möglicherweise nicht gerechtfertigt, sich mit der Dokumentation für die Entwicklung komplexerer Berichtsformulare vertraut zu machen. In anderen Fällen ist JasperReports eine gute Open Source-Lösung für die Berichtsautomatisierung.