Erstellen von PDF-Dateien in Java

1. Einleitung

In diesem kurzen Artikel konzentrieren wir uns darauf, PDF-Dokumente von Grund auf neu zu erstellen, basierend auf der beliebten iText- und PdfBox-Bibliothek.

2. Maven-Abhängigkeiten

Werfen wir einen Blick auf die Maven-Abhängigkeiten, die in unser Projekt aufgenommen werden müssen:

 com.itextpdf itextpdf 5.5.10   org.apache.pdfbox pdfbox 2.0.4 

Die neueste Version der Bibliotheken finden Sie hier: iText und PdfBox.

Zum Hinzufügen ist eine zusätzliche Abhängigkeit erforderlich, falls unsere Datei verschlüsselt werden muss. Das Bounty Castle Provider-Paket enthält Implementierungen kryptografischer Algorithmen und wird von beiden Bibliotheken benötigt:

 org.bouncycastle bcprov-jdk15on 1.56  

Die neueste Version der Bibliothek finden Sie hier: The Bounty Castle Provider.

3. Übersicht

Sowohl iText als auch PdfBox sind Java-Bibliotheken, die zum Erstellen / Bearbeiten von PDF-Dateien verwendet werden. Obwohl die endgültige Ausgabe der Bibliotheken dieselbe ist, arbeiten sie auf etwas andere Weise. Schauen wir sie uns an.

4. Erstellen Sie ein PDF in IText

4.1. Text in Pdf einfügen

Schauen wir uns an, wie eine neue Datei mit dem Text „Hello World“ in die PDF-Datei eingefügt wird

Document document = new Document(); PdfWriter.getInstance(document, new FileOutputStream("iTextHelloWorld.pdf")); document.open(); Font font = FontFactory.getFont(FontFactory.COURIER, 16, BaseColor.BLACK); Chunk chunk = new Chunk("Hello World", font); document.add(chunk); document.close();

Das Erstellen eines PDF- Dokuments unter Verwendung der iText-Bibliothek basiert auf der Bearbeitung von Objekten, die die Elements- Schnittstelle in Document implementieren (in Version 5.5.10 gibt es 45 dieser Implementierungen).

Das kleinste Element, das dem Dokument hinzugefügt und verwendet werden kann, heißt Chunk . Dies ist im Grunde eine Zeichenfolge mit angewendeter Schriftart.

Darüber hinaus können Chunks mit anderen Elementen wie Absätzen , Abschnitten usw. kombiniert werden , was zu gut aussehenden Dokumenten führt.

4.2. Bild einfügen

Die iText-Bibliothek bietet eine einfache Möglichkeit, dem Dokument ein Bild hinzuzufügen. Wir müssen lediglich eine Image- Instanz erstellen und dem Dokument hinzufügen .

Path path = Paths.get(ClassLoader.getSystemResource("Java_logo.png").toURI()); Document document = new Document(); PdfWriter.getInstance(document, new FileOutputStream("iTextImageExample.pdf")); document.open(); Image img = Image.getInstance(path.toAbsolutePath().toString()); document.add(img); document.close();

4.3. Tabelle einfügen

Wir könnten auf ein Problem stoßen, wenn wir unserem PDF eine Tabelle hinzufügen möchten. Glücklicherweise bietet iText eine solche sofort einsatzbereite Funktionalität.

Zunächst müssen wir ein PdfTable- Objekt erstellen und im Konstruktor eine Reihe von Spalten für unsere Tabelle bereitstellen. Jetzt können wir einfach eine neue Zelle hinzufügen, indem wir anrufen

Jetzt können wir einfach eine neue Zelle hinzufügen, indem wir die addCell- Methode für das neu erstellte Tabellenobjekt aufrufen . iText erstellt Tabellenzeilen, solange alle erforderlichen Zellen definiert sind. Wenn Sie also eine Tabelle mit 3 Spalten erstellen und 8 Zellen hinzufügen, werden nur 2 Zeilen mit jeweils 3 Zellen angezeigt.

Schauen wir uns das Beispiel an:

Document document = new Document(); PdfWriter.getInstance(document, new FileOutputStream("iTextTable.pdf")); document.open(); PdfPTable table = new PdfPTable(3); addTableHeader(table); addRows(table); addCustomRows(table); document.add(table); document.close();

Wir erstellen eine neue Tabelle mit 3 Spalten und 3 Zeilen. Die erste Zeile wird als Tabellenüberschrift mit geänderter Hintergrundfarbe und Randbreite behandelt:

private void addTableHeader(PdfPTable table) { Stream.of("column header 1", "column header 2", "column header 3") .forEach(columnTitle -> { PdfPCell header = new PdfPCell(); header.setBackgroundColor(BaseColor.LIGHT_GRAY); header.setBorderWidth(2); header.setPhrase(new Phrase(columnTitle)); table.addCell(header); }); }

Die zweite Zeile besteht aus drei Zellen, nur mit Text, ohne zusätzliche Formatierung.

private void addRows(PdfPTable table) { table.addCell("row 1, col 1"); table.addCell("row 1, col 2"); table.addCell("row 1, col 3"); }

Wir können nicht nur Text in Zellen, sondern auch Bilder einfügen. Darüber hinaus kann jede Zelle einzeln formatiert werden. In dem unten dargestellten Beispiel werden horizontale und vertikale Ausrichtungsanpassungen angewendet:

private void addCustomRows(PdfPTable table) throws URISyntaxException, BadElementException, IOException { Path path = Paths.get(ClassLoader.getSystemResource("Java_logo.png").toURI()); Image img = Image.getInstance(path.toAbsolutePath().toString()); img.scalePercent(10); PdfPCell imageCell = new PdfPCell(img); table.addCell(imageCell); PdfPCell horizontalAlignCell = new PdfPCell(new Phrase("row 2, col 2")); horizontalAlignCell.setHorizontalAlignment(Element.ALIGN_CENTER); table.addCell(horizontalAlignCell); PdfPCell verticalAlignCell = new PdfPCell(new Phrase("row 2, col 3")); verticalAlignCell.setVerticalAlignment(Element.ALIGN_BOTTOM); table.addCell(verticalAlignCell); }

4.4. Dateiverschlüsselung

Um die Berechtigung mithilfe der iText-Bibliothek anwenden zu können, müssen Sie bereits ein PDF-Dokument erstellt haben. In unserem Beispiel verwenden wir unsere zuvor generierte Datei iTextHelloWorld.pdf .

Sobald wir die Datei mit PdfReader geladen haben , müssen wir einen PdfStamper erstellen , mit dem zusätzliche Inhalte auf Dateien wie Metadaten, Verschlüsselung usw. angewendet werden:

PdfReader pdfReader = new PdfReader("HelloWorld.pdf"); PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileOutputStream("encryptedPdf.pdf")); pdfStamper.setEncryption( "userpass".getBytes(), ".getBytes(), 0, PdfWriter.ENCRYPTION_AES_256 ); pdfStamper.close();

In unserem Beispiel haben wir die Datei mit zwei Passwörtern verschlüsselt. Das Benutzerkennwort („Benutzerpass“), bei dem ein Benutzer nur schreibgeschützt ist und keine Möglichkeit zum Drucken hat, sowie das Besitzerkennwort („Eigentümerpass“), das als Hauptschlüssel verwendet wird, damit eine Person uneingeschränkten Zugriff auf PDF hat.

Wenn wir dem Benutzer erlauben möchten, PDF zu drucken, können wir anstelle von 0 (dritter Parameter von setEncryption ) Folgendes übergeben:

PdfWriter.ALLOW_PRINTING

Natürlich können wir verschiedene Berechtigungen mischen wie:

PdfWriter.ALLOW_PRINTING | PdfWriter.ALLOW_COPY

Beachten Sie, dass wir mit iText zum Festlegen von Zugriffsberechtigungen auch ein temporäres PDF erstellen, das gelöscht werden sollte und andernfalls für jedermann vollständig zugänglich sein könnte.

5. Erstellen Sie ein PDF in der PdfBox

5.1. Text in Pdf einfügen

Im Gegensatz zum iText bietet die PdfBox- Bibliothek eine API, die auf Stream-Manipulation basiert. Es gibt keine Klassen wie Chunk / Paragraph usw. Die PDDocument- Klasse ist eine speicherinterne Pdf-Darstellung, in die der Benutzer Daten durch Manipulieren der PDPageContentStream- Klasse schreibt .

Schauen wir uns das Codebeispiel an:

PDDocument document = new PDDocument(); PDPage page = new PDPage(); document.addPage(page); PDPageContentStream contentStream = new PDPageContentStream(document, page); contentStream.setFont(PDType1Font.COURIER, 12); contentStream.beginText(); contentStream.showText("Hello World"); contentStream.endText(); contentStream.close(); document.save("pdfBoxHelloWorld.pdf"); document.close();

5.2. Bild einfügen

Das Einfügen von Bildern ist unkompliziert.

First we need to load a file and create a PDImageXObject, subsequently draw it on the document (need to provide exact x,y coordinates).

That's all:

PDDocument document = new PDDocument(); PDPage page = new PDPage(); document.addPage(page); Path path = Paths.get(ClassLoader.getSystemResource("Java_logo.png").toURI()); PDPageContentStream contentStream = new PDPageContentStream(document, page); PDImageXObject image = PDImageXObject.createFromFile(path.toAbsolutePath().toString(), document); contentStream.drawImage(image, 0, 0); contentStream.close(); document.save("pdfBoxImage.pdf"); document.close(); 

5.3. Inserting a Table

Unfortunately, PdfBox does not provide any out-of-box methods allowing creating tables. What we can do in such situation is to draw it manually – literally, draw each line until our drawing resembles our dreamed table.

5.4. File Encryption

PdfBox library provides a possibility to encrypt, and adjust file permission for the user. Comparing to iText, it does not require to use an already existing file, as we simply use PDDocument. Pdf file permissions are handled by AccessPermission class, where we can set if a user will be able to modify, extract content or print a file.

Subsequently, we create a StandardProtectionPolicy object which adds password-based protection to the document. We can specify two types of password. The user password, after which person will be able to open a file with applied access permissions and owner password (no limitations to the file):

PDDocument document = new PDDocument(); PDPage page = new PDPage(); document.addPage(page); AccessPermission accessPermission = new AccessPermission(); accessPermission.setCanPrint(false); accessPermission.setCanModify(false); StandardProtectionPolicy standardProtectionPolicy = new StandardProtectionPolicy("ownerpass", "userpass", accessPermission); document.protect(standardProtectionPolicy); document.save("pdfBoxEncryption.pdf"); document.close(); 

In unserem Beispiel wird die Situation dargestellt, dass die Datei nicht geändert und gedruckt werden kann, wenn ein Benutzer ein Benutzerkennwort angibt.

6. Schlussfolgerungen

In diesem Tutorial haben wir Möglichkeiten zum Erstellen einer PDF-Datei in zwei gängigen Java-Bibliotheken erläutert.

Vollständige Beispiele finden Sie im Maven-basierten Projekt auf GitHub.