Création de fichiers PDF en Java

1. Introduction

Dans cet article rapide, nous nous concentrerons sur la création d'un document PDF à partir de zéro basé sur les bibliothèques populaires iText et PdfBox.

2. Dépendances de Maven

Jetons un coup d'œil aux dépendances Maven, qui doivent être incluses dans notre projet:

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

La dernière version des bibliothèques peut être trouvée ici: iText et PdfBox.

Une dépendance supplémentaire est nécessaire à ajouter, au cas où notre fichier aurait besoin d'être chiffré. Le package Bounty Castle Provider contient des implémentations d'algorithmes cryptographiques et est requis par les deux bibliothèques:

 org.bouncycastle bcprov-jdk15on 1.56  

La dernière version de la bibliothèque se trouve ici: The Bounty Castle Provider.

3. Aperçu

Les deux, iText et PdfBox sont des bibliothèques java utilisées pour la création / manipulation de fichiers pdf. Bien que la sortie finale des bibliothèques soit la même, elles fonctionnent de manière légèrement différente. Jetons un coup d'œil à eux.

4. Créer un PDF dans IText

4.1. Insérer du texte en PDF

Voyons comment un nouveau fichier avec le texte «Hello World» est inséré dans un fichier pdf

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

La création d'un pdf avec une utilisation de la bibliothèque iText est basée sur la manipulation d'objets implémentant l' interface Elements dans Document (dans la version 5.5.10 il y a 45 de ces implémentations).

Le plus petit élément qui peut être ajouté au document et utilisé est appelé Chunk , qui est essentiellement une chaîne avec une police appliquée.

De plus, les blocs peuvent être combinés avec d'autres éléments comme les paragraphes , la section, etc., ce qui donne de beaux documents.

4.2. Insérer une image

La bibliothèque iText fournit un moyen simple d'ajouter une image au document. Nous devons simplement créer une instance Image et l'ajouter au document .

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. Insérer un tableau

Nous pourrions être confrontés à un problème lorsque nous souhaitons ajouter un tableau à notre pdf. Heureusement, iText fournit une telle fonctionnalité prête à l'emploi.

Tout d'abord, ce que nous devons faire est de créer un objet PdfTable et dans le constructeur de fournir un certain nombre de colonnes pour notre table. Maintenant, nous pouvons simplement ajouter une nouvelle cellule en appelant

Maintenant, nous pouvons simplement ajouter une nouvelle cellule en appelant la méthode addCell sur l'objet table nouvellement créé. iText créera des lignes de tableau tant que toutes les cellules nécessaires sont définies, ce que cela signifie est qu'une fois que vous créez un tableau avec 3 colonnes et y ajoutez 8 cellules, seules 2 lignes avec 3 cellules chacune seront affichées.

Jetons un œil à l'exemple:

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

Nous créons un nouveau tableau avec 3 colonnes et 3 lignes. La première ligne que nous traiterons comme un en-tête de tableau avec une couleur d'arrière-plan et une largeur de bordure modifiées:

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

La deuxième ligne sera composée de trois cellules uniquement avec du texte, sans mise en forme supplémentaire.

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

Nous pouvons inclure non seulement du texte dans les cellules mais aussi des images. De plus, chaque cellule peut être formatée individuellement, dans l'exemple présenté ci-dessous, nous appliquons des ajustements d'alignement horizontal et vertical:

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. Chiffrement de fichiers

Pour appliquer l'autorisation à l'aide de la bibliothèque iText, nous devons avoir déjà créé un document PDF. Dans notre exemple, nous utiliserons notre fichier iTextHelloWorld.pdf généré précédemment.

Une fois que nous avons chargé le fichier à l'aide de PdfReader , nous devons créer un PdfStamper qui est utilisé pour appliquer un contenu supplémentaire au fichier comme les métadonnées, le cryptage, etc.

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

Dans notre exemple, nous avons chiffré le fichier avec deux mots de passe. Le mot de passe de l'utilisateur («userpass») où un utilisateur n'a qu'un droit en lecture seule sans possibilité de l'imprimer, et le mot de passe du propriétaire («ownerpass») qui est utilisé comme clé principale permettant à une personne d'avoir un accès complet au pdf.

Si nous voulons permettre à l'utilisateur d'imprimer le pdf, au lieu de 0 (troisième paramètre de setEncryption ) nous pouvons passer:

PdfWriter.ALLOW_PRINTING

Bien sûr, nous pouvons mélanger différentes autorisations telles que:

PdfWriter.ALLOW_PRINTING | PdfWriter.ALLOW_COPY

Gardez à l'esprit qu'en utilisant iText pour définir les autorisations d'accès, nous créons également un pdf temporaire qui devrait être supprimé et sinon, il pourrait être entièrement accessible à tout le monde.

5. Créer un Pdf dans PdfBox

5.1. Insérer du texte en PDF

Contrairement à iText , la bibliothèque PdfBox fournit une API basée sur la manipulation de flux. Il n'y a pas de classes comme Chunk / Paragraph etc. La classe PDDocument est une représentation Pdf en mémoire où l'utilisateur écrit des données en manipulant la classe PDPageContentStream .

Jetons un coup d'œil à l'exemple de code:

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. Insérer une image

L'insertion d'images est simple.

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

Notre exemple présente une situation dans laquelle si un utilisateur fournit un mot de passe utilisateur, le fichier ne peut pas être modifié et imprimé.

6. Conclusions

Dans ce didacticiel, nous avons discuté des moyens de créer un fichier PDF dans deux bibliothèques Java populaires.

Des exemples complets peuvent être trouvés dans le projet basé sur Maven sur GitHub.