Correva l'anno 2009 quando una giovane Serena scriveva un interessante post sulla modalità con cui valorizzare i placeholder all'interno di un PDF; per chi se lo fosse perso vi invito a leggere il post originale.
Sono passati ormai un pò di anni, i sistemi sono cambiati ma le esigenze sono rimaste le stesse ed infatti oggi mi sono ritrovato a dover fare la medesima cosa: valorizzare i placeholder all'interno di un PDF.
Il post originale è stato di grande ispirazione ma purtroppo alcune librerie sono cambiate ed ho dovuto fare qualche modifica al codice; modifica che voglio condividere con voi... e con me stesso quando tra qualche mese dovrò rifarlo nuovamente!
Innanzitutto io sto lavorando con Liferay 7.1.3 e di conseguenza la prima cosa da fare è configurare correttamente tutte le dipendenze. Nel mio caso utilizzerò solamente alcuni pacchetti forniti dalla libreria iText7; pertanto aggiungiamo le seguenti righe all'interno del file build.gradle
:
compileInclude group: "com.itextpdf", name: "kernel", version: "7.1.6"
compileInclude group: "com.itextpdf", name: "forms", version: "7.1.6"
Queste sono le uniche librerie che ci servono perchè l'unica cosa che dobbiamo fare è valorizzare i placeholder all'interno di un PDF che già esiste; la versione 7.1.6 è la più recente al momento in cui sto scrivendo questo post.
In realtà queste librerie si portano dietro altre dipendenze, che a noi non servono, pertanto andiamo anche ad inserire le seguenti righe all'interno del file bnd.bnd
:
Import-Package: \
!org.bouncycastle.*,\
!org.slf4j.impl.*,\
*
A questo punto facciamo un bel "gradle refresh" e deployamo tutto per verificare che le dipendenze siano tutte soddisfatte.
Veniamo ora al codice da usare per valorizzare i placeholder e salvare il file di output; siccome stiamo parlando di file e di Liferay, diamo per scontato che il codice seguente sia inserito all'interno del metodo serveResource
della nostra portlet in modo da consentirci di salvarlo.
import com.itextpdf.forms.PdfAcroForm;
import com.itextpdf.forms.fields.PdfFormField;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfWriter;
// Recupero dalla Document Library del PDF contenente i placeholder
FileEntry fileEntry = ...
// Creazione reader del PDF
PdfReader reader = new PdfReader(fileEntry.getContentStream());
// File di output
File file = FileUtil.createTempFile();
PdfWriter writer = new PdfWriter(file);
// Creazione del documento
PdfDocument pdfDocument = new PdfDocument(reader, writer);
// Form contenente i campi del PDF da riempire
PdfAcroForm form = PdfAcroForm.getAcroForm(pdfDocument, true);
form.setGenerateAppearance(true);
// Recupero e valorizzazione dei placeholder
Map<String, PdfFormField> fields = form.getFormFields();
fields.get("nome_campo_1").setValue("...");
fields.get("nome_campo_1").setValue("...");
fields.get("nome_campo_1").setValue("...");
// Valorizzare dei placeholder rimanenti
// Rende i placeholder del PDF non modificabili
form.flattenFields();
pdfDocument.close();
writer.close();
reader.close();
String fileName = fileEntry.getFileName();
// Download del file
PortletResponseUtil.sendFile(
resourceRequest, resourceResponse, fileName,
FileUtil.getBytes(file), MimeTypesUtil.getContentType(file));
Chiaramente potete anche decidere si salvare il file di output nella Document Libray anzichè farne il download...