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.
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 |
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.
22 février 2010 at 11 h 28 min
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
26 février 2010 at 9 h 22 min
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);
}
24 avril 2010 at 8 h 48 min
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
12 juillet 2010 at 12 h 54 min
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.
30 juillet 2014 at 11 h 29 min
Bonjour,
je suis débutante sur alfresco je veux savoir comment je pourrai appliquer le filigrane automatiquement sur les documents pdf (Automatiser l’application du filigrane dès que le document est un pdf)? Pouvez-vous me donner des indications svp, merci beaucoup.
25 août 2014 at 9 h 04 min
Bonjour,
L’action d’ajout du filigrane peut être déclenchée par une règle de gestion Alfresco, paramétrable sur un répertoire depuis l’interface. Ainsi, vous pouvez ajouter le filigrane sur tout document entrant dans un espace donné.
Ceci étant, comme précisé dans l’article, il manque encore l’interface de saisie du paramètre « watermark-text ».
11 novembre 2014 at 21 h 00 min
Bonjour,
Le module n’est plus disponible en amp pour alfresco share 5 ?
Cordialement.
12 novembre 2014 at 9 h 32 min
Bonjour,
Non en effet, le module n’a pas été porté vers la dernière version d’Alfresco.
La partie « entrepôt » me semble utilisable en l’état, mais il faudrait développer l’interfaçage avec Alfresco Share.
Cordialement.