Introduction

Lorsqu’un service juridique reçoit plusieurs PDF de contrats, chaque relecteur ajoute souvent son propre mot de passe pour protéger les clauses confidentielles. Consolider ces fichiers en un seul classeur devient un cauchemar parce que les mots de passe diffèrent et les fichiers ne peuvent pas être fusionnés directement. Le déchiffrement manuel est long et sujet aux erreurs, surtout lorsqu’il s’agit de dizaines de PDF.

Le password‑merge est un flux de travail GroupDocs.Merger pour Java qui déverrouille des PDF hétérogènes et reprotège le résultat fusionné avec un seul jeu d’identifiants. Ce tutoriel montre comment détecter les PDF protégés, les déverrouiller, fusionner le contenu et, éventuellement, faire pivoter le mot de passe unifié.

Vous apprendrez à configurer l’API Merger, à traiter les flux d’octets et à générer un PDF combiné sécurisé en moins de 30 lignes de code Java.

Quand faut‑il fusionner des PDF protégés par mot de passe ?

Fusionner des PDF protégés par mot de passe a du sens chaque fois que vous avez besoin d’une archive unique et consultable qui respecte les politiques de sécurité tout en éliminant la surcharge de gestion de plusieurs mots de passe. Les scénarios typiques incluent les lots de rapports financiers trimestriels, les classeurs de contrats pour les audits et les dossiers juridiques où chaque contributeur a appliqué un mot de passe différent. En déverrouillant chaque fichier de façon programmatique et en appliquant un mot de passe unique, vous maintenez la sécurité de l’archive et simplifiez les processus de révision en aval. L’ensemble de l’opération peut être automatisé dans un pipeline CI, économisant des heures de travail manuel.

Prérequis

  • Java 11 ou version ultérieure
  • GroupDocs.Merger for Java 24.6+ (licence temporaire)
  • Un ensemble de fichiers PDF, chacun éventuellement associé à son mot de passe

Installez la bibliothèque via Maven :

mvn dependency:copy -Dartifact=com.groupdocs:groupdocs-merger:24.6

Étape 1 – Détecter si un PDF est protégé par mot de passe

Avant d’essayer de déverrouiller un fichier, vérifiez s’il possède réellement un mot de passe. Cela évite un traitement inutile et vous permet de consigner quels fichiers nécessitent des identifiants.

// Returns true if the PDF at `path` has an owner or user password
public boolean isDocumentProtected(String path, String password) {
    Merger merger;
    if (password == null || password.isEmpty()) {
        merger = new Merger(path);
    } else {
        merger = new Merger(path, new LoadOptions(password));
    }
    try {
        return merger.isPasswordSet();
    } finally {
        merger.dispose();
    }
}

Points clés :

  • LoadOptions transporte un mot de passe connu ; s’il n’est pas fourni, le fichier est ouvert normalement.
  • isPasswordSet() renvoie true tant pour les mots de passe propriétaire que pour les mots de passe utilisateur.
  • Disposez toujours de l’instance Merger pour libérer les ressources natives.

Étape 2 – Déverrouiller chaque PDF et collecter les octets bruts

Parcourez une map où la clé est le chemin du fichier et la valeur son mot de passe (null si aucun). La méthode renvoie une liste de tableaux d’octets représentant les PDF déverrouillés.

public List<byte[]> unlockAll(Map<String, String> sources) throws IOException {
    List<byte[]> unlocked = new ArrayList<>();
    for (Map.Entry<String, String> e : sources.entrySet()) {
        String path = e.getKey();
        String password = e.getValue();
        System.out.println("Unlocking (credentials=" +
                (password != null ? "yes" : "no") + "): " + path);
        if (password == null || password.isEmpty()) {
            unlocked.add(Files.readAllBytes(Paths.get(path)));
        } else {
            LoadOptions opts = new LoadOptions(password);
            ByteArrayOutputStream buf = new ByteArrayOutputStream();
            Merger m = new Merger(path, opts);
            try {
                m.removePassword();
                m.save(buf);
            } finally {
                m.dispose();
            }
            unlocked.add(buf.toByteArray());
        }
    }
    return unlocked;
}

Points clés :

  • removePassword() supprime la protection existante.
  • Le contenu déchiffré est écrit dans un ByteArrayOutputStream pour une gestion en mémoire.
  • Les fichiers sans mot de passe sont lus directement afin de simplifier le flux.

Étape 3 – Fusionner les PDF déverrouillés et appliquer un mot de passe unique

Créez un Merger à partir du premier flux PDF, puis ajoutez les flux restants. Enfin, protégez le document combiné avec AddPasswordOptions.

public void mergeAndProtect(List<byte[]> unlockedPdfs,
                            String unifiedPassword,
                            String outputPath) {
    InputStream first = new ByteArrayInputStream(unlockedPdfs.get(0));
    Merger merger = new Merger(first);
    try {
        for (int i = 1; i < unlockedPdfs.size(); i++) {
            merger.join(new ByteArrayInputStream(unlockedPdfs.get(i)));
        }
        merger.addPassword(new AddPasswordOptions(unifiedPassword));
        merger.save(outputPath);
    } finally {
        merger.dispose();
    }
    System.out.println("Merged output: " + new File(outputPath).getAbsolutePath());
    System.out.println("Unified password: " + unifiedPassword);
}

Points clés :

  • addPassword chiffre le PDF final avec le mot de passe fourni.
  • Toutes les opérations se déroulent en mémoire ; seul le fichier final est écrit sur le disque.
  • Disposez du Merger pour libérer les poignées natives.

Étape 4 – Faire pivoter le mot de passe sur un PDF déjà protégé (optionnel)

Si votre organisation impose une rotation périodique des mots de passe, vous pouvez mettre à jour les identifiants sans re‑fusionner les fichiers sources.

public void rotateUnifiedPassword(String path,
                                 String oldPassword,
                                 String newPassword,
                                 String outputPath) {
    Merger merger = new Merger(path, new LoadOptions(oldPassword));
    try {
        merger.updatePassword(new UpdatePasswordOptions(newPassword));
        merger.save(outputPath);
    } finally {
        merger.dispose();
    }
    System.out.println("Rotated output: " + new File(outputPath).getAbsolutePath());
    System.out.println("New password: " + newPassword);
}

Points clés :

  • Chargez le PDF protégé avec le mot de passe actuel.
  • updatePassword le remplace par le nouveau.
  • Cette opération est rapide car elle ne retraite pas le contenu du PDF.

Application concrète

Je l’ai rencontrée en consolidant cinq contrats d’investisseurs, chacun avec un mot de passe de relecteur différent. En suivant les étapes ci‑dessus, j’ai déverrouillé tous les fichiers, les ai fusionnés en un seul classeur et appliqué un mot de passe unique conforme à notre politique d’entreprise. L’ensemble du processus s’est exécuté en moins de deux minutes sur un ordinateur portable standard.

Bonnes pratiques

  • Valider les mots de passe dès le départ : utilisez isDocumentProtected pour identifier les fichiers qui pourraient nécessiter une intervention manuelle.
  • Limiter l’utilisation de la mémoire : pour les PDF volumineux, écrivez‑les sur disque plutôt que de conserver tous les tableaux d’octets en mémoire.
  • Libérer les objets rapidement : la classe Merger détient des ressources natives ; appelez toujours dispose() dans un bloc finally.
  • Utiliser une licence temporaire uniquement pendant le développement ; obtenez une licence de production avant la mise en production.

Conclusion

GroupDocs.Merger for Java fournit une API claire pour déverrouiller, fusionner et re‑sécuriser des collections de PDF. En suivant les quatre étapes — détection de la protection, déverrouillage, fusion avec un mot de passe unique et, éventuellement, rotation de ce mot de passe—vous pouvez automatiser la création de classeurs PDF sécurisés sans intervention manuelle.

Prochaines étapes :

  • Explorez des options supplémentaires comme la définition des métadonnées PDF après la fusion (documentation).
  • Apprenez à fusionner des PDF tout en conservant les signets (API reference).
  • Consultez le projet d’exemple complet sur GitHub pour une implémentation prête à l’emploi.

Ressources supplémentaires