Convertire HTML in PDF

Quante volte avete dovuto trasformare un file HTML in PDF in un progetto? E’ una di quelle cose che vengono richieste frequentemente in un progetto e allora vediamo quali sono le possibili soluzioni per ottenere questo risultato in Java

iText

iText è una libreria opensource che permette di creare/modificare documenti PDF tramite API Java. Inizialmente sviluppato da Bruno Lowagie e Paulo Soares, il progetto è cresciuto negli anni ed è stato fatto anche un porting in .NET. Inizialmente la libreria era disponibile con la licenza opensource LGPL, mentre l’ultima versione è ora rilasciata sotto la licenza AGPL in aggiunta alla versione commerciale. Per provare a trasformare HTML in PDF ho inserito tre diversi esempi, utili per valutare alcune situazioni in cui ci possiamo trovare ovvero

  1. Semplice : html banale con quasi nessun markup specifico oltre al testo
  2. Standard : diversi tag html, bold, elenchi numerati etc. etc.
  3. Immagini e CSS : html che include immagini e CSS

Nella nostra classe di test che utilizza iText richiameremo quindi dei metodi per la stampa dei PDF dando in input i diversi HTML come riportato di seguito

Il metodo pdfTest è quello che riesce a supportare facilmente la conversione dei primi due esempi. Utilizzando la classe di utility XMLWorkerHelper e dandogli in pasto l’HTML che dobbiamo convertire, iText riesce a creare semplicemente i nostri PDF.

Per quanto riguarda invece l’esempio con immagine e CSS il discorso cambia e dobbiamo scavare un pò nell’API di iText. La prima cosa di cui ci dobbiamo occupare è la trasformazione del nostro HTML in un XHTML. Questo può essere fatto utilizzando librerie come JTidy o JSoup. In questo caso abbiamo utilizzato JSoup specificando che vogliamo bonificare il nostro HTML utilizzando una sintassi XML

Dopo questo dobbiamo utilizzare l’API di iText che prevede una serie di pipeline per gestire i diversi contenuti del nostro file HTML, come potete vedere dal seguente esempio

Il PDF risultante include i CSS e l’immagine ma il font utilizzato non è quello che abbiamo specificato noi e alcune cose sui bordi CSS non vengono rispettate. Per ottenere il risultato uguale all’HTML di partenza dovremmo agire sui font da includere nel PDF e sul CSS, facendo diventare ancora più laboriosa questa conversione.

 

FlyingSaucer

Dopo aver provato iText vale la pena dare un’occhiata a FlyingSaucer che utilizza iText ma cercando di fornire un API più snella, anche perchè lo scopo principale della libreria è diverso da iText in quanto si propone come renderer generico per documenti XML (o XHTML) che utilizzano CSS per layout e formattazione. Uno degli output è appunto il PDF che viene gestito tramite iText in diverse modalità

  1. org.xhtmlrenderer:flying-saucer-pdf – iText 2.x (versione LGPL)
  2. org.xhtmlrenderer:flying-saucer-pdf-itext5 – iText 5.x (versione AGPL)
  3. org.xhtmlrenderer:flying-saucer-pdf-openpdf – OpenPDF (fork di iText 4)

Negli esempi che abbiamo realizzato è stata utilizzata la versione vecchia LGPL, anche per verificare le differenze rispetto alla nuova versione. Procediamo quindi con gli stessi HTML d’esempio realizzando anche in questo caso un primo metodo che riesce a gestire le prime due casistiche

In questo caso facciamo riferimento alla classe ITextRender, alla quale forniamo direttamente l’URL dell’HTML che vogliamo trasformare e abbiamo semplicemente generato il PDF. I file creati sono la fedele conversione dei sorgenti HTML e in più rispetto alla generazione standard con iText (quindi senza scavare troppe nelle feature dell’API) vediamo che il PDF generato ha i paragrafi nell’indice.

Il metodo che genera il terzo HTML è quasi uguale a quello già visto, l’unica cosa che dobbiamo fare, come con iText, è ripulire l’HTML dall’imperfezione in questo caso del tag img (che in HTML non richiede la chiusura).