PDF-Dokumente mit Wasserzeichen versehen

Gerade wenn Dokumente an Dritte herausgegeben werden sollen, besteht oft die Anforderung diese mit einem Wasserzeichen oder einer besonderen Markierung zu versehen. Wenn der Erzeugungsprozess dieser Dokumente bereits mit jadice server durchgeführt wird, ist es ein Leichtes einen weiteren Verarbeitungsschritt in den Konvertierungsworkflow einzufügen.

Hierzu bietet jadice server zwei grundlegend verschiedene Ansätze, wie dies umgesetzt werden kann:

  1. Einsatz eines PageDecorators, wenn ein Dokument mit den Mitteln der jadice document platform als PDF neu gerendert wird.
    Dieses Vorgehen empfiehlt sich dann, wenn ein Dokument in einem Format vorliegt, das von der jadice document platform nativ unterstützt wird und mittels des JadiceShaperNodes in PDF konvertiert wird.
  2. Über ein bereits bestehendes PDF-Dokument wird eine "Maske" gelegt, die in einem zweiten PDF vorab generiert wurde.
    Dieses Vorgehen bietet sich insbesondere dann an, wenn
    • das PDF-Dokument bereits vorliegt,
    • während eines vorherigen Schrittes im Workflow erzeugt wird oder
    • ein Neu-Rendern mit den Mitteln der jadice document platform vermieden werden soll.

Verwendung eines PageDecorators im JadiceShaperNode

Beim Rendern eines Datenstroms mit dem JadiceShaperNode können Implementierung des Interface PageDecorator verwendet werden, wie sie in der jadice document platform eingesetzt werden. Ein solcher PageDecorator kann mittels Graphics2D-Operationen beliebige eigene Inhalte über oder unter dem eigentlichen Seiteninhalt aufbringen.

Zum schnellen Einstieg bietet jadice server eine einfache Musterimplementierung, mit der Texte auf der Dokumentseite platziert werden können. Die Klasse com.levigo.jadice.server.jadice4x.HeaderFooterPageDecorator finden Sie in der Datei base-nodes-server-4.x.x.x.jar. Zur Verwendung müssen Sie diese JAR-Datei und die Datei shaper-base-4.x.x.x.jar, die sich im Verzeichnis <jadice-server>/server-lib/ befinden, in den Klassenpfad Ihrer Anwendung aufnehmen.

Über einfache setter-Methoden können Sie clientseitig einen Text, die Schriftart sowie Position und Ausrichtung definieren:

Clientseitiger Code: Wasserzeichen durch PageDecorator
// Konfiguration des JadiceShaperNodes
StreamInputNode inputNode = new StreamInputNode();
JadiceShaperNode shaperNode = new JadiceShaperNode();
shaperNode.setTargetMimeType("application/pdf");

// Konfiguration des beiliegenden PageDecorators
PageDecorator simpleDecorator = new HeaderFooterPageDecorator();
simpleDecorator.setTemplate("DUPLIKAT");
simpleDecorator.setFont(new Font("Arial", Font.BOLD, 30));
simpleDecorator.setTextOrientation(-45.0f);
simpleDecorator.setHorizontalAlignment(HorizontalAlignment.CENTER);
simpleDecorator.setVerticalAlignment(VerticalAlignment.CENTER);
shaperNode.getSettings(BaseShaperSettings.class).setPageDecorator(simpleDecorator);

// Einbinden in einen Workflow und Aufruf eines Jobs siehe: jadice server Entwicklerhandbuch

Haben Sie bereits eine eigene Implementierung eines PageDecorators vorliegen, z.B. weil dieser in einer Integration des jadice viewers verwendet wird, kann dieser ebenfalls für die Konvertierung in jadice server eingesetzt werden.

Voraussetzung hierfür ist, dass Ihr PageDecorator und all seine Parameter serialisierbar sind und dementsprechend das Marker-Interface java.io.Serializable implementieren. Diese Klasse muss sowohl im Klassenpfad Ihrer Client-Applikation wie auch im Klassenpfad von jadice server eingebunden werden. Der Aufruf erfolgt in gleicher Weise wie zum oben gezeigten Codebeispiel.

Überlagern mit Inhalten eines zweiten PDF-Dokumente

Im ersten Schritt dieses Szenario wird davon ausgegangen, dass das einzubrennende Wasserzeichen immer gleich bleibt und als (einseitiges) PDF-Dokument vorliegt. Außerdem wird davon ausgegangen, dass das Dokument mit dem Inhalt ebenso bereits als PDF vorliegt.

Achten Sie beim Erstellen des Wasserzeichen-PDFs darauf, dass dieses einen transparenten Hintergrund hat. Andernfalls werden die restlichen Dokumentinhalte verdeckt.

Mit Hilfe des PDFCompositeNodes können das PDF mit dem Inhalt und das PDF mit dem Wasserzeichen zusammengefügt werden:

Clientseitiger Code: PDFs übereinanderlegen
// Konfiguration des Workflows
StreamInputNode inputNode = new StreamInputNode();
PDFCompositeNode compositeNode = new PDFCompositeNode();

// Konfiguration des PDFCompositeNode
compositeNode.setRepeat(true); // Wiederholen des Wasserzeichens
compositeNode.setOrder(Order.BACK_TO_FRONT); // Wasserzeichen über Inhalt

// Einbinden in einen Workflow und Aufruf eines Jobs siehe: jadice server Entwicklerhandbuch
(...)

// Senden der Datenströme an jadice server
InputStream myDocumentStream = ...;
InputStream myWatermarkPDFStream = ...;
inputNode.addStream(myDocumentStream);
inputNode.addStream(myWatermarkPDFStream);
inputNode.complete();

Für den Anwendungsfall, dass das Dokument mit dem Inhalt zuvor durch jadice server zu konvertieren ist, muss der Workflow dahingehend angepasst werden, dass dieses Dokument und das Wasserzeichen über unterschiedliche Knoten zum PDFCompositeNode gelangen.

Clientseitiger Code: Dokument und Wasserzeichen unterschiedlich verarbeiten
// Konfiguration des Workflows
StreamInputNode documentInputNode = new StreamInputNode();
Node myConversionNode = ...// entspr. Node zur Dokumentkonvertierung
StreamInputNode watermarkInputNode = new StreamInputNode();
DemultiplexerNode demux = new DemultiplexerNode();
PDFCompositeNode compositeNode = new PDFCompositeNode();

// Konfiguration des PDFCompositeNode
compositeNode.setRepeat(true); // Wiederholen des Wasserzeichens
compositeNode.setOrder(Order.BACK_TO_FRONT); // Wasserzeichen über Inhalt

// Einbinden in einen Workflow und Aufruf eines Jobs siehe: jadice server Entwicklerhandbuch
documentInputNode.appendSuccessor(myConversionNode).appendSuccessor(demux);
watermarkInputNode.appendSuccessor(demux);
demux.appendSuccessor(compositeNode);

// Senden der Datenströme an jadice server
InputStream myDocumentStream = ...;
documentInputNode.addStream(myDocumentStream);
documentInputNode.complete();

InputStream myWatermarkPDFStream = ...;
watermarkInputNode.addStream(myWatermarkPDFStream);
watermarkInputNode.complete();

Besteht darüber hinaus die Anforderung, dass auch das Wasserzeichen dynamisch generiert werden soll, kann dies z.B. mit XSL-FO erzeugt werden. Wie dies funktioniert, erklärt Ihnen der Knowledge Base-Artikel "Von der Textdatei zum PDF".