Für einen Anwendungsfall musste ich PDFs mit einander Verketten / Mergen, hierzu nutze ich die PDF Box der Version 1.5.0 in meinem Projekt. Leider musste ich immer wieder feststellen das es zu Fehlern kam und ich machte mich auf die Fehlersuche. Als Lösung musste ich in Java PDF flatten (flach machen), damit ich diese verwenden konnte.
Nach einer sehr groß angelegten Fehlersuche, bin ich zu dem Entschluss gekommen das es an den Bestandteilen von einem PDF liegen kann. Ein PDF Dokument verfügt über ca. 14 verschiedene Elemente in einer Art Baumstruktur, welche beim Verketten / Mergen sich gegenseitig beeinflussen. Dies konnte man gut daran erkennen, das es Fehler bei der Ausführung von JavaScript kam.
Die Herausgeber der Formulare benutzen JavaScript zum Berechnen von Werte und Anderem.Ich möchte die Dokumente miteinander verketten. Formularfelder, JavaScript brauche ich nicht in den Verketteten PDFs, da es kein Sinn macht Formulare in mit einem 50 seitigen Dokument anzuhängen.
Ich mache meine Dokumente flach und entferne alles unnötige wie:
- JavaScript
- JS
- OpenAction
- Forms
- AA
- Launch
In dem Code entferne ich einfach aus dem Strukturbaum eines PDF Dokumentes die oben erwähnten Elemente.
DER CODE
Für mein Codebeispiel benutze ich die Bibliothek iText, welche man hier runterladen kann – iText.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
import java.io.FileOutputStream; import java.io.IOException; import com.itextpdf.text.DocumentException; import com.itextpdf.text.pdf.AcroFields; import com.itextpdf.text.pdf.PdfDictionary; import com.itextpdf.text.pdf.PdfName; import com.itextpdf.text.pdf.PdfObject; import com.itextpdf.text.pdf.PdfReader; import com.itextpdf.text.pdf.PdfStamper; /** * @author ST-Page.de * @file PDFFlattener.java * @date 16.12.2013 * */ public class PDFFlattener { /** * Remove different elements from a pdf document like JS, JavaScript, * OpenAction, Action or XFA. * * @param pdfold * {@link String} with filepath * @param pdfnew * {@link String} with new filepath * @return * @throws Exception * if document is not at the filepath */ public void flattenPDF(String pdfold, String pdfnew) throws Exception { try { PdfReader pdfReader = new PdfReader(pdfold); if (!pdfReader.isEncrypted()) { PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileOutputStream(pdfnew)); AcroFields form = pdfStamper.getAcroFields(); PdfObject object; PdfDictionary action; // start remove the bad thinks into a PDF Object[] keys = form.getFields().keySet().toArray(); for (int i = 0; i < keys.length; i++) { form.removeField((String) keys[i]); } for (int i = 1; i < pdfReader.getXrefSize(); i++) { object = pdfReader.getPdfObject(i); if (object instanceof PdfDictionary) { action = ((PdfDictionary) object).getAsDict(PdfName.A); ((PdfDictionary) object).remove(PdfName.JAVASCRIPT); ((PdfDictionary) object).remove(PdfName.JS); ((PdfDictionary) object).remove(PdfName.AA); ((PdfDictionary) object).remove(PdfName.OPENACTION); ((PdfDictionary) object).remove(PdfName.XFA); if (action == null) continue; if (PdfName.LAUNCH.equals(action.getAsName(PdfName.S))) { action.remove(PdfName.F); action.remove(PdfName.WIN); } } } pdfStamper.getReader().removeFields(); pdfStamper.getReader().removeUnusedObjects(); pdfStamper.getReader().removeUsageRights(); pdfStamper.createXmpMetadata(); pdfStamper.close(); pdfReader.close(); return; } else { System.out .println("Das Dokument wurde mit einem Passwort versehen und kann nicht bearbeitet werden."); pdfReader.close(); return; } } catch (IOException e) { e.printStackTrace(); } catch (DocumentException e) { e.printStackTrace(); } } /** * @param args * 0 => file path of the old document (PDF with XFA, JS) * 1 => filepath of the new document (the flatten PDF) */ public static void main(String[] args) { if (args.length == 2) { try { PDFFlattener flattener = new PDFFlattener(); flattener.flattenPDF(args[0], args[1]); System.out.println("Status OK - 200"); } catch (Exception e) { e.printStackTrace(); } } else { System.out .println("The start argument are old file path and new file path."); } } } |