Creazione di file PDF in Java

1. Introduzione

In questo rapido articolo, ci concentreremo sulla creazione di documenti PDF da zero basati sulla popolare libreria iText e PdfBox.

2. Dipendenze di Maven

Diamo un'occhiata alle dipendenze di Maven, che devono essere incluse nel nostro progetto:

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

L'ultima versione delle librerie può essere trovata qui: iText e PdfBox.

È necessaria un'ulteriore dipendenza da aggiungere, nel caso in cui il nostro file debba essere crittografato. Il pacchetto Bounty Castle Provider contiene implementazioni di algoritmi crittografici ed è richiesto da entrambe le librerie:

 org.bouncycastle bcprov-jdk15on 1.56  

L'ultima versione della libreria può essere trovata qui: The Bounty Castle Provider.

3. Panoramica

Entrambi, iText e PdfBox sono librerie java utilizzate per la creazione / manipolazione di file pdf. Sebbene l'output finale delle librerie sia lo stesso, funzionano in modo leggermente diverso. Diamo un'occhiata a loro.

4. Crea PDF in IText

4.1. Inserisci testo in Pdf

Diamo uno sguardo al modo in cui un nuovo file con testo "Hello World" viene inserito nel file 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 creazione di un pdf con l'uso della libreria iText si basa sulla manipolazione di oggetti che implementano l' interfaccia Elements in Document (nella versione 5.5.10 ci sono 45 di queste implementazioni).

L'elemento più piccolo che può essere aggiunto al documento e utilizzato è chiamato Chunk , che è fondamentalmente una stringa con un carattere applicato.

Inoltre, i Chunk possono essere combinati con altri elementi come Paragraphs , Section ecc. Risultando in documenti dall'aspetto piacevole.

4.2. Inserimento dell'immagine

La libreria iText fornisce un modo semplice per aggiungere un'immagine al documento. Abbiamo semplicemente bisogno di creare un'istanza di immagine e aggiungerla al documento .

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. Inserimento tabella

Potremmo incontrare un problema quando vorremmo aggiungere una tabella al nostro pdf. Fortunatamente iText fornisce tale funzionalità out-of-the-box.

Innanzitutto quello che dobbiamo fare è creare un oggetto PdfTable e nel costruttore fornire un numero di colonne per la nostra tabella. Ora possiamo semplicemente aggiungere una nuova cella chiamando

Ora possiamo semplicemente aggiungere una nuova cella chiamando il metodo addCell sull'oggetto tabella appena creato. iText creerà le righe della tabella finché tutte le celle necessarie sono definite, ciò significa che una volta creata una tabella con 3 colonne e aggiunto 8 celle, verranno visualizzate solo 2 righe con 3 celle ciascuna.

Diamo un'occhiata all'esempio:

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

Creiamo una nuova tabella con 3 colonne e 3 righe. La prima riga verrà considerata come un'intestazione di tabella con un colore di sfondo e una larghezza del bordo modificati:

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 seconda riga sarà composta da tre celle solo con testo, senza formattazione aggiuntiva.

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

Possiamo includere non solo testo nelle celle ma anche immagini. Inoltre, ogni cella potrebbe essere formattata individualmente, nell'esempio presentato di seguito applichiamo regolazioni di allineamento orizzontale e verticale:

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. Crittografia dei file

Per applicare l'autorizzazione utilizzando la libreria iText, è necessario aver già creato un documento PDF. Nel nostro esempio, useremo il nostro file iTextHelloWorld.pdf generato in precedenza.

Una volta caricato il file utilizzando PdfReader , dobbiamo creare un PdfStamper che viene utilizzato per applicare contenuti aggiuntivi al file come metadati, crittografia, ecc:

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

Nel nostro esempio, abbiamo crittografato il file con due password. La password dell'utente ("userpass") in cui un utente ha il diritto di sola lettura senza possibilità di stamparla e la password del proprietario ("ownerpass") che viene utilizzata come chiave principale consentendo a una persona di avere pieno accesso al pdf.

Se vogliamo consentire all'utente di stampare il pdf, invece di 0 (terzo parametro di setEncryption ) possiamo passare:

PdfWriter.ALLOW_PRINTING

Naturalmente, possiamo combinare diverse autorizzazioni come:

PdfWriter.ALLOW_PRINTING | PdfWriter.ALLOW_COPY

Tieni presente che utilizzando iText per impostare i permessi di accesso, stiamo anche creando un pdf temporaneo che dovrebbe essere eliminato e in caso contrario potrebbe essere completamente accessibile a chiunque.

5. Crea Pdf in PdfBox

5.1. Inserisci testo in Pdf

Al contrario di iText , la libreria PdfBox fornisce un'API basata sulla manipolazione del flusso. Non ci sono classi come Chunk / Paragraph ecc. La classe PDDocument è una rappresentazione Pdf in memoria in cui l'utente scrive i dati manipolando la classe PDPageContentStream .

Diamo un'occhiata all'esempio di codice:

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. Inserimento dell'immagine

L'inserimento di immagini è semplice.

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

Il nostro esempio presenta una situazione in cui se un utente fornisce la password utente, il file non può essere modificato e stampato.

6. Conclusioni

In questo tutorial, abbiamo discusso i modi per creare un file pdf in due popolari librerie Java.

Esempi completi possono essere trovati nel progetto basato su Maven su GitHub.