Recherche sur le blog

mardi 12 janvier 2016

[Java] Regrouper plusieurs PDF en un seul

Avec la librairie PDFBox, vous pouvez regrouper plusieurs documents PDF en un seul, de manière assez simple. Dans les exemples que je vais donner ici, j'ai utilisé la version 2.0.0-RC2. Vous la retrouverez sur la page de téléchargement du site web. Si vous utilisiez une version 1.x, n'hésitez pas à consulter le guide de migration et la liste de dépendances

Si vos fichiers ne sont pas protégés contre l'ouverture et/ou la modification alors le code est relativement simple à mettre en place.
PDFMergerUtility ut = new PDFMergerUtility();
ut.addSource(FICHIER1);
ut.addSource(FICHIER2);
ut.addSource(FICHIER3);
ut.setDestinationFileName(NOM_FICHIER);
ut.mergeDocuments();
Nous utiliserons une instance de la classe PDFMergerUtility, du package "org.apache.pdfbox.multipdf" (ceci vous sera utile pour l'import). Il faut ensuite ajouter chaque fichier source afin de constituer la liste des fichiers à regrouper. Le paramètre de la fonction addSource() peut être une chaine de caractères représentant le chemin du fichier, un objet de type File, ou un objet de type InputStream.

Une fois tous les éléments ajoutés, il faut spécifier le nom du fichier destination avec setDestinationFileName(). Cette fonction est disponible pour notre objet PDFMergerUtility précédemment créé. Ensuite, comme le montre l'exemple, on demande à ce que les documents soient tous regroupés. On effectue cette action avec la fonction mergeDocuments().

Si par contre vos fichiers sont protégés contre la modification (par exemple, à l'aide d'un mot de passe), alors il faudra procéder de manière légèrement différente.
final java.util.ArrayList<PDDocument> tobeclosed =
 new java.util.ArrayList<>();
try (PDDocument dest = new PDDocument()) {
   PDDocument src1 = PDDocument.load(fic1,password);
   src1.setAllSecurityToBeRemoved(true);
   src1.save(fic1);
   merge.appendDocument(dest, src1);
   tobeclosed.add(src1);

   PDDocument src2 = PDDocument.load(fic2,password);
   src1.setAllSecurityToBeRemoved(true);
   src1.save(fic2);
   merge.appendDocument(dest, src2);
   tobeclosed.add(src2);

   ...
}
On a tout d'abord déclaré un tableau - nommé "tobeclosed" - auquel on ajoutera tous les documents PDF qu'on souhaite regrouper, car ils vont être ouverts pour pouvoir être ajoutés à tour de rôle. Il ne faut pas les fermer avant que le document final ne soit sauvegardé. Pour chaque document, on déclare donc une instance de la classe PDDocument, et on appelle la fonction load() de celle-ci pour lancer le chargement. La fonction prendra en paramètre une variable de type File et le mot de passe.

On fait ensuite en sorte d'enlever toutes les protections du document. Pour cela l'objet dispose d'une fonction appelée setAllSecurityToBeRemoved(). En paramètre, on lui donne un booléen dont la valeur est Vrai. On sauve ensuite le document, à l'aide de save() en spécifiant à nouveau l'objet File.

Le document sauvé, on va ajouter le document aux autres, à l'aide de la fonction appendDocument() de notre objet PDFMergerUtility. Les 2 paramètres sont de type PDDocument. On donne, dans l'ordre, le document de destination et ensuite le document source à ajouter. Ensuite, il faut ajouter ce dernier dans le fameux tableau qu'on a créé au tout début (voir l'exemple).

Une fois tous les fichiers sélectionnés...
dest.save(f);
Le document de destination doit être sauvegardé - dest.save(). Il faut ajouter cette instruction au code d'exemple précédent, avant l'accolade de fermeture de la clause "try".

Un petit conseil : si vous devez laisser la protection active dans les fichiers d'origine, alors il vaut mieux passer par des copies. Dans mon cas je copie les PDF dans le répertoire temporaire de l'utilisateur, puis j'effectue le traitement de regroupement. Petite astuce pour obtenir le répertoire temporaire (à partir du JDK 7) :
String tmpFolder = System.getProperty("java.io.tmpdir");
Bon développement !

Aucun commentaire: