Après la conversion vers PDF/A, nous nous intéressons aujourd’hui à une autre fonctionnalité liée au format de fichier PDF implémentable dans Alfresco : l’insertion d’un texte en filigrane.

Cette insertion est rendue possible par un simple développement utilisant les API mises à disposition par Alfresco, la configuration du client web, et la librairie iText.

iText [en] est une API JAVA permettant de générer des documents PDF, ainsi que de modifier des documents PDF existants. Cette API est disponible gratuitement, sous licence MPL et LGPL.

Les actions dans Alfresco

Une action au sens Alfresco est une unité de travail, exécutée sur un document ou un espace, et que l’on peut actionner depuis l’interface standard (depuis la fiche de propriétés d’un élément, sélectionner « Lancer une action ») ou automatiser via les règles de gestion.

Il est possible, via une configuration, de mettre à disposition des utilisateurs une nouvelle action écrite en Java comme indiqué dans le wiki Alfresco [en]. Ce développement est facilité par les classes de base Alfresco, ce qui nous permet de nous consacrer pleinement à l’application du filigrane.

package com.atolcd.repo.action.executer;
 
import java.io.File;
import java.io.FileOutputStream;
import java.util.List;
 
import org.alfresco.model.ContentModel;
import org.alfresco.repo.action.ParameterDefinitionImpl;
import org.alfresco.repo.action.executer.ActionExecuterAbstractBase;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.action.ParameterDefinition;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.util.TempFileProvider;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
 
import com.lowagie.text.pdf.BaseFont;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfStamper;
 
public class PDFWatermarkActionExecuter extends ActionExecuterAbstractBase
	implements InitializingBean {
 
    public static final String NAME = "watermark";
    public static final String PARAM_TEXT = "watermark-text";
 
    private ContentService contentService;
 
    public void setContentService(ContentService contentService) {
	this.contentService = contentService;
    }
 
    public void afterPropertiesSet() throws Exception {
	Assert.notNull(contentService);
    }
 
    @Override
    protected void executeImpl(Action action, NodeRef actionedUponNodeRef) {
	ContentReader reader = contentService.getReader(actionedUponNodeRef,
		ContentModel.PROP_CONTENT);
 
	if (MimetypeMap.MIMETYPE_PDF.equals(reader.getMimetype())) {
	    PdfReader pdfReader = null;
	    PdfStamper stamper = null;
	    try {
		pdfReader = new PdfReader(reader.getContentInputStream());
		File newPdf = TempFileProvider.createTempFile("tmp",
			"watermark");
		FileOutputStream fos = new FileOutputStream(newPdf);
		stamper = new PdfStamper(pdfReader, fos);
		BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA,
			BaseFont.WINANSI, BaseFont.NOT_EMBEDDED);
		PdfContentByte under;
		int total = pdfReader.getNumberOfPages() + 1;
		for (int i = 1; i < total; i++) {
		    under = stamper.getUnderContent(i);
		    under.beginText();
		    under.setFontAndSize(bf, 18);
		    under.setTextMatrix(0, 0.5f, -0.5f, 0, 30, 30);
		    under.showText((String) action
			    .getParameterValue(PARAM_TEXT));
		    under.endText();
		}
		stamper.close();
 
		ContentWriter writer = contentService.getWriter(
			actionedUponNodeRef, ContentModel.PROP_CONTENT, true);
		writer.putContent(newPdf);
	    } catch (Exception e) {
		e.printStackTrace();
	    }
	}
    }
 
    @Override
    protected void addParameterDefinitions(List paramList) {
	paramList
		.add(new ParameterDefinitionImpl(PARAM_TEXT,
			DataTypeDefinition.TEXT, true,
			getParamDisplayLabel(PARAM_TEXT)));
    }
}

La classe PDFWatermarkActionExecuter est réduite à sa plus simple expression : une méthode addParameterDefinitions permettant de gérer les paramètres et une méthode executeImpl chargée de l’application de notre filigrane : un texte passé en paramètre de l’action, avec une position, une orientation, une police et une taille fixées.

Il serait possible d’améliorer cette action en permettant à l’utilisateur de paramétrer plus finement (police, taille, etc…) le filigrane, voire d’utiliser une image en complément (ou à la place) du texte.

Il est à noter qu’un autre développement est nécessaire afin d’obtenir une interface adaptée à la saisie dudit paramètre (encore une fois, direction le wiki[en]).

Module

L’action est ici proposée sous forme de module, facilement installable dans une instance Alfresco [en], comportant :

  • le code Java chargé de l’ajout du filigrane sur toutes les pages d’un document PDF,
  • le morceau d’interface permettant de passer en paramètre le texte que l’on souhaite insérer,
  • la configuration ajoutant l’action dans l’interface standard.

Télécharger le projet Eclipse du module.

Taggué avec :
 

4 Responses to Alfresco – Insérer un filigrane sur les document PDF avec iText

  1. WIATR Thomas dit :

    Bonjour,

    Je suis très intéressé par ce script, car j’aimerais l’utiliser pour mettre en filigrane de mes document pdf un identifiant unique généré par alfresco.

    – J’ai créé l’identifiant via un aspect dans les propriétés du document (propriété appelée ‘custom:DocID’).

    – Mais je ne sais pas comment faire pour que WaterMark prenne cette valeur comme texte de filigrane à la place du texte statique saisi dans l’interface Watermark alfresco

    PS : Je ne connais du tout Java, ça aide pas…

    Merci d’avance

    • Bertrand Magnier dit :

      Bonjour,

      Le paramètre “text” est actuellement inséré dans le PDF par cette ligne :
      under.showText((String) action.getParameterValue(PARAM_TEXT));

      Ce qu’il faut faire, c’est remplacer “action.getParameterValue(PARAM_TEXT)” par la récupération de votre propriété custom:DocID.
      Pour ce faire, on va utiliser la méthode getProperty du NodeService (http://dev.alfresco.com/resource/docs/java/repository/org/alfresco/service/cmr/repository/NodeService.html):
      under.showText((String) nodeService.getProperty(actionedUponNodeRef, QName.createQName("custom", "DocID")));

      Et pour pouvoir utiliser ce NodeService, il faut l’injecter dans notre classe PDFWatermarkActionExecuter de la même manière que le ContentService déjà utilisé.
      Soit, dans le fichier module-context.xml :

      et au début de notreclasse Java

      private ContentService contentService;
      private NodeService nodeService;
      public void setContentService(ContentService contentService) {
      this.contentService = contentService;
      }
      public void setNodeService(NodeService nodeService) {
      this.nodeService = nodeService;
      }

      public void afterPropertiesSet() throws Exception {
      Assert.notNull(contentService);
      Assert.notNull(nodeService);
      }

  2. Michal dit :

    Hi, thnx a lot for posting project.. it helaps me a lot whe working with changing of pdf documents :)
    I want to add more parameters so your project is super base stone..
    br
    Michal

  3. Edward Lobo dit :

    I have installed abbyyocr to convert tiff documents to readable pdf with a RuntimeExecutableContentTransformerWorker as explained here: http://wiki.alfresco.com/wiki/Content_Transformations

    This works just fine however I now need a way to convert image pdf to readable pdf. I dont think I can use the above method to call abbyyocr. Is there any other way ?

    Many thanks.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Vous pouvez utiliser ces balises et attributs HTML : <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>