Introduction
Коли юридичний відділ отримує кілька PDF‑документів з контрактами, кожен рецензент часто додає власний пароль для захисту конфіденційних пунктів. Об’єднання цих файлів в один том стає справжнім кошмаром, оскільки паролі різні і файли не можна з’єднати безпосередньо. Ручне розшифрування займає багато часу і схильне до помилок, особливо коли мова йде про десятки PDF‑файлів.
Password‑merge — це робочий процес GroupDocs.Merger для Java, який розблоковує різнорідні PDF‑файли та повторно захищає результат об’єднання одним спільним паролем. У цьому підручнику розглядаються кроки виявлення захищених PDF, їх розблокування, об’єднання вмісту та, за потреби, ротація єдиного пароля.
Ви дізнаєтеся, як налаштувати API Merger, працювати з байтовими потоками та створювати захищений комбінований PDF у менш ніж 30 рядках коду Java.
When should I merge password‑protected PDFs?
Об’єднання PDF‑файлів, захищених паролем, має сенс, коли потрібен один, придатний до пошуку архів, який відповідає політикам безпеки і одночасно усуває необхідність керувати кількома паролями. Типові сценарії включають квартальні пакети фінансових звітів, збірки контрактів для аудиту та юридичні справи, де кожен учасник застосував інший пароль. Розблокувавши кожен файл програмно і застосувавши єдиний пароль, ви зберігаєте безпеку архіву та спрощуєте подальші процеси перегляду. Увесь процес можна автоматизувати в CI‑конвеєрі, заощаджуючи години ручної роботи.
Prerequisites
- Java 11 або новіша
- GroupDocs.Merger for Java 24.6+ (temporary license)
- Набір PDF‑файлів, кожен з яких за потреби має свій пароль
Встановіть бібліотеку за допомогою Maven:
mvn dependency:copy -Dartifact=com.groupdocs:groupdocs-merger:24.6
Step 1 – Detect if a PDF is password‑protected
Before attempting to unlock a file, check whether it actually carries a password. This avoids unnecessary processing and lets you log which files need credentials.
// 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();
}
}
Key points:
LoadOptionscarries a known password; if none is provided the file is opened normally.isPasswordSet()reports true for both owner and user passwords.- Always dispose the
Mergerinstance to free native resources.
Step 2 – Unlock each PDF and collect raw bytes
Iterate over a map where the key is the file path and the value is its password (null if none). The method returns a list of byte arrays representing the unlocked PDFs.
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;
}
Key points:
removePassword()strips the existing protection.- The decrypted content is written to a
ByteArrayOutputStreamfor in‑memory handling. - Files without a password are read directly to keep the flow simple.
Step 3 – Merge the unlocked PDFs and apply a unified password
Create a Merger from the first PDF stream, then join the remaining streams. Finally, protect the combined document with 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);
}
Key points:
addPasswordencrypts the final PDF with the supplied credential.- All operations happen in memory; only the final file is written to disk.
- Dispose the
Mergerto release native handles.
Step 4 – Rotate the password on an already‑protected PDF (optional)
If your organization enforces periodic password rotation, you can update the credential without re‑merging the source files.
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);
}
Key points:
- Load the protected PDF with the current password.
updatePasswordreplaces it with the new credential.- This operation is fast because it does not re‑process the PDF content.
Real‑World Application
I hit this when consolidating five investor contracts that each had a different reviewer password. Using the steps above, I unlocked all files, merged them into a single binder, and applied a single password that matched our corporate policy. The whole process ran in under two minutes on a standard laptop.
Best Practices
- Validate passwords early: Use
isDocumentProtectedto flag files that may need manual attention. - Limit memory usage: For large PDFs, stream them to disk instead of keeping all byte arrays in memory.
- Dispose objects promptly: The Merger class holds native resources; always call
dispose()in afinallyblock. - Use a temporary license only for development; obtain a production license before release.
Conclusion
GroupDocs.Merger for Java provides a clean API for unlocking, merging, and re‑securing PDF collections. By following the four steps—detecting protection, unlocking, merging with a unified password, and optionally rotating that password—you can automate the creation of secure PDF binders without manual intervention.
Next steps:
- Explore additional options such as setting PDF metadata after merge (documentation).
- Learn how to merge PDFs while preserving bookmarks (API reference).
- Check out the full sample project on GitHub for a ready‑to‑run implementation.