Apache PDFBox: una libreria Java per lavorare con i documenti PDF

Apache PDFBox: una libreria Java per lavorare con i documenti PDF

In questo articolo vedremo come utilizzare la libreria Java Apache PDFBox per manipolare documenti in formato PDF. PDFBox è una libreria Java rilasciata con licenza Open Source (Apache License v2.0), la quale permette di creare un nuovo documento PDF, manipolare documenti esistenti ed estrarre il contenuto da questi documenti. E' possibile inoltre scaricarne una versione stand-alone (cioè che funziona senza dover sviluppare codice che la utilizzi), che permette di effettuare una serie di operazioni agendo direttamente da linea di comando.

Creare un file eseguibile .exe per le applicazioni Java con Launch4j
Apache MyFaces: un’implementazione Open Source delle specifiche JSF
iText: creare PDF in Java

In questo articolo vedremo come utilizzare la libreria Java Apache PDFBox per manipolare documenti in formato PDF. PDFBox è una libreria Java rilasciata con licenza Open Source (Apache License v2.0), la quale permette di creare un nuovo documento PDF, manipolare documenti esistenti ed estrarre il contenuto da questi documenti.

E’ possibile inoltre scaricarne una versione stand-alone (cioè che funziona senza dover sviluppare codice che la utilizzi), che permette di effettuare una serie di operazioni agendo direttamente da linea di comando.

Vediamo ora come è strutturato Apache PDFBox, dopo di che faremo degli esempi pratici in Java.

I documenti PDF sono degli stream di oggetti di tipo base, questi oggetti di basso livello sono rappresentati in PDFBox nel package org.apache.pdfbox.cos package. Gli oggetti base in PDF sono:

PDF TypeDescrizioneEsempioClassi PDFBox
ArrayUna lista ordinata di elementi[1 2 3]org.apache.pdfbox
.cos.COSArray
BooleanI valori True/Falsetrueorg.apache.pdfbox

.cos.COSBoolean

DictionaryUna mappa di coppie chiave/valore<<
/Type /XObject
/Name (Name)
/Size 1
>>
org.apache.pdfbox 

.cos.COSDictionary

NumberNumeri Interi e in virgola mobile1 2.3org.apache.pdfbox 

.cos.COSFloat
org.apache.pdfbox


.cos.COSInteger

NameUn valore predefinito in un documento PDF, usato tipicamente come chiave in un dizionario/Typeorg.apache.pdfbox 

.cos.COSName

ObjectUn Wrapper per ogni altrotipo di oggetto, il quale può essere utilizzato per referenziare un oggetto per più volte. Un oggetto è referenziato utilizzando due numeri: un number object e un generation number. All’inizio il generation number è 0 fino a che l’oggetto non venga rimpiazzato più tardi nello stream.12 0 obj << /Type /XObject >> endobjorg.apache.pdfbox 

.cos.COSObject

StreamUno stream di dati il più delle volte compresso. Questo viene usato per il contenuto della pagina, le immagini e per i font.12 0 obj << /Type /XObject >> stream 030004040404040404 endstreamorg.apache.pdfbox 

.cos.COSStream

StringUna sequenza di caratteri.(This is a string)org.apache.pdfbox 

.cos.COSString

Il modello basato su oggetti COS permette di accedere a qualsiasi elemento del documento PDF, ma per accedervi l’utente deve conoscere il nome dei parametri che vuole usare e ciò porta ad inevitabili errori. Di conseguenza è stato creato un altro Modello (PD Model) che offre delle agevolazioni per il programmatore. Ogni oggetto del documento ha un set di attributi definiti che possono essere disponibili nel dizionario. La libreria fornisce una classe PD Model per ogni tipo di oggetto del documento le quali forniscono dei metodi fortemente tipizzati che permetto di accedere agli attributi definiti. Di conseguenza il PD Model è collocabile al di sopra del COS Model come mostrato in figura:

Struttura del COS Model e del PD Model

Ovviamente nei nostri esempi faremo sempre uso delle classi del PD Model.

A questo punto scarichiamo la libreria all’indirizzo:

http://pdfbox.apache.org/download.html

scegliendo il file .jar pdfbox-version.jar (la 1.5.0 nel momento in cui scriviamo), dobbiamo inoltre scaricare sempre dalla stessa pagina il file di dipendenza .jsr fontbox-version.jar (è un componente stand-alone che permette di manipolare i formati dei font).

Una ulteriore dipendenza da soddisfare è la libreria commons-logging che possiamo scaricare da questa url:

http://apache.panu.it//commons/logging/binaries/commons-logging-1.1.1-bin.zip

Utilizzeremo per i nostri esempi Java l’IDE Eclipse.

Creiamo un nuovo Progetto Java in Eclipse (File -> New -> Java Project), creiamo una cartella lib e vi copiamo le libreria pdfbox-1.5.0.jar, fontbox-1.5.0.jar e commons-logging-1.1.1.jar, per cui avremo il nostro progetto così strutturato:

La struttura del nostro Progetto Java

Dobbiamo poi includerle nel Build Path del nostro progetto: click col tasto destro sul progetto -> Build Path -> Configure Build Path):

  • pdfbox-1.5.0.jar;
  • fontbox-1.5.0.jar;
  • commons-logging-1.1.1.jar.
Il Java Build Path del progetto

Creiamo ora una classe Java per poter provare la libreria (tasto destro sulla cartella src -> New -> Class), ed indichiamo il nome, il package e la JVM da utilizzare come riportato in figura:

Creiamo la nostra classe Java di esempio

Aggiungiamo del codice per creare una pagina PDF con un testo in una certa posizione della pagina:

package it.appuntisoftware;

import java.io.IOException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.edit.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType1Font;

public class test {
  public static void main(String[] args) throws Exception{
    PDDocument doc = null;
    try{
      doc = new PDDocument();
      PDPage page = new PDPage();
      doc.addPage( page );
      PDPageContentStream contentStream = new PDPageContentStream(doc, 
      page);
      PDFont font = PDType1Font.HELVETICA_BOLD;
      contentStream.beginText();
      contentStream.setFont( font, 12 );
      contentStream.moveTextPositionByAmount( 100, 700 );
      contentStream.drawString("Ciao da 
      AppuntiSoftware.it");
      contentStream.endText();
      contentStream.close();
      doc.save("output.pdf");
      doc.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
 }

}

Con il codice precedente viene creato un file pdf dal nome output.pdf che viene salvato nella directory root del nostro progetto, all’interno del quale viene scritta la Stringa che abbiamo passato all’oggetto PDPageContentStream. Come vediamo la prima cosa da fare è creare un documento PDF (istanza di PDDocument) e poi aggiungervi una pagina (istanza di PDPage) con il metodo addPage().

A questo punto istanziamo uno stream a cui passiamo come argomento il documento e la pagina su cui agire. Abbiamo inoltre settato un font (Helvetica_Bold) col metodo setFont (prima lo abbiamo definito utilizzando un campo statico della classe PDType1Font). Con il metodo moveTextPositionByAmount( x , y) posizioniamo il cursore da cui iniziare a scrivere, è importante notare che nei documenti PDF la posizione (0 , 0 ) rappresenta l’angolo in basso a sinistra. Dopo aver chiuso lo stream possiamo procedere al salvataggio con il metodo save(nomefile).

Scriviamo un’altra classe in cui andiamo ad aprire un file pdf già esistente, lo modifichiamo e lo scriviamo su di un altro file:

package it.appuntisoftware;

import java.io.IOException;
import org.apache.pdfbox.exceptions.COSVisitorException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.edit.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType1Font;

public class TestPDFBox {

 public static void main(String[] args){
  PDDocument doc = null;
  try{
    doc = PDDocument.load("output.pdf" );
    PDPage page = (PDPage)doc.getDocumentCatalog().getAllPages().get(0);
    PDPageContentStream contentStream = new PDPageContentStream(doc, page, 
    true, true);
    PDFont font = PDType1Font.HELVETICA_BOLD;
    contentStream.beginText();
    contentStream.setFont( font, 12 );
    contentStream.moveTextPositionByAmount( 260, 700 );
    contentStream.drawString( "!!!!!" );
    contentStream.endText();
    contentStream.close();
    doc.save("outputMod.pdf");
    doc.close();
  } catch (IOException e) {
    e.printStackTrace();
  } catch (COSVisitorException e) {
    e.printStackTrace();
  }
 }
}

Le differenze con il precedente esempio sono l’utilizzo di PDDocument.load(nomefile) con il quale carichiamo in memoria il file  e con doc.getDocumentCatalog().getAllPages().get(indexpagina) recuperiamo la lista di tutte le pagine e ci posizioniamo sulla prima.

COMMENTS

WORDPRESS: 0