บทนำ
เมื่อแผนกกฎหมายได้รับ PDF สัญญาหลายไฟล์ ผู้ตรวจสอบแต่ละคนมักจะเพิ่มรหัสผ่านของตนเองเพื่อปกป้องข้อกำหนดที่เป็นความลับ การรวมไฟล์เหล่านี้เป็นโฟลเดอร์เดียวกลายเป็นเรื่องน่าสะพรึงกลัวเพราะรหัสผ่านต่างกันและไฟล์ไม่สามารถรวมกันได้โดยตรง การถอดรหัสด้วยมือใช้เวลานานและเสี่ยงต่อข้อผิดพลาด โดยเฉพาะเมื่อต้องจัดการกับหลายสิบไฟล์ PDF
Password‑merge เป็น workflow ของ GroupDocs.Merger สำหรับ Java ที่ปลดล็อก PDF ที่มีความแตกต่างกันและปกป้องผลลัพธ์ที่รวมแล้วด้วยข้อมูลประจำตัวเดียว บทเรียนนี้จะอธิบายขั้นตอนการตรวจจับ PDF ที่มีการป้องกัน, ถอดรหัส, รวมเนื้อหา, และหากต้องการก็เปลี่ยนรหัสผ่านที่รวมไว้
คุณจะได้เรียนรู้วิธีกำหนดค่า Merger API, ประมวลผลสตรีมไบต์, และสร้าง PDF ที่รวมกันอย่างปลอดภัยในโค้ด Java ไม่เกิน 30 บรรทัด
ควรจะรวม PDF ที่มีการป้องกันด้วยรหัสผ่านเมื่อใด?
การรวม PDF ที่มีการป้องกันด้วยรหัสผ่านมีความสมเหตุสมผลเมื่อคุณต้องการคลังข้อมูลเดียวที่สามารถค้นหาได้และยังคงรักษานโยบายความปลอดภัยไว้ขณะกำจัดภาระการจัดการรหัสผ่านหลายชุด สถานการณ์ทั่วไปรวมถึงชุดรายงานการเงินรายไตรมาส, โฟลเดอร์สัญญาสำหรับการตรวจสอบ, และไฟล์คดีกฎหมายที่ผู้ร่วมทำงานแต่ละคนใช้รหัสผ่านต่างกัน โดยการปลดล็อกแต่ละไฟล์โดยอัตโนมัติและใช้รหัสผ่านเดียว คุณจะทำให้คลังข้อมูลปลอดภัยและทำให้กระบวนการตรวจสอบต่อไปง่ายขึ้น ทั้งหมดนี้สามารถทำอัตโนมัติใน pipeline CI เพื่อประหยัดเวลาหลายชั่วโมงจากการทำงานด้วยมือ
ข้อกำหนดเบื้องต้น
- Java 11 หรือใหม่กว่า
- GroupDocs.Merger for Java 24.6+ (temporary license)
- ชุดไฟล์ PDF ที่แต่ละไฟล์อาจมีรหัสผ่านคู่กัน
ติดตั้งไลบรารีผ่าน Maven:
mvn dependency:copy -Dartifact=com.groupdocs:groupdocs-merger:24.6
ขั้นตอนที่ 1 – ตรวจจับว่า PDF มีการป้องกันด้วยรหัสผ่านหรือไม่
ก่อนพยายามถอดรหัสไฟล์ ให้ตรวจสอบว่ามีรหัสผ่านหรือไม่ เพื่อหลีกเลี่ยงการประมวลผลที่ไม่จำเป็นและบันทึกไฟล์ที่ต้องการข้อมูลประจำตัว
// 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();
}
}
ประเด็นสำคัญ:
LoadOptionsจะบรรจุรหัสผ่านที่ทราบ; หากไม่มีจะเปิดไฟล์ตามปกติisPasswordSet()คืนค่า true ทั้งสำหรับรหัสผ่านเจ้าของและผู้ใช้- ควร
disposeอินสแตนซ์Mergerเสมอเพื่อปล่อยทรัพยากรเนทีฟ
ขั้นตอนที่ 2 – ถอดรหัส PDF แต่ละไฟล์และเก็บไบต์ดิบ
วนลูปผ่านแผนที่ที่คีย์เป็นเส้นทางไฟล์และค่าเป็นรหัสผ่าน (null หากไม่มี) วิธีนี้จะคืนรายการอาเรย์ไบต์ที่แทน PDF ที่ถอดรหัสแล้ว
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;
}
ประเด็นสำคัญ:
removePassword()ลบการป้องกันที่มีอยู่- เนื้อหาที่ถอดรหัสจะถูกเขียนลง
ByteArrayOutputStreamเพื่อจัดการในหน่วยความจำ - ไฟล์ที่ไม่มีรหัสผ่านจะอ่านโดยตรงเพื่อให้กระบวนการง่ายขึ้น
ขั้นตอนที่ 3 – รวม PDF ที่ถอดรหัสแล้วและใส่รหัสผ่านเดียว
สร้าง Merger จากสตรีม PDF แรก แล้วต่อสตรีมที่เหลือเข้ามา สุดท้ายปกป้องเอกสารที่รวมแล้วด้วย 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);
}
ประเด็นสำคัญ:
addPasswordเข้ารหัส PDF สุดท้ายด้วยข้อมูลประจำตัวที่ระบุ- ทุกอย่างทำในหน่วยความจำ; มีเพียงไฟล์ผลลัพธ์สุดท้ายที่เขียนลงดิสก์
disposeMergerเพื่อปล่อยแฮนด์เนิลเนทีฟ
ขั้นตอนที่ 4 – เปลี่ยนรหัสผ่านบน PDF ที่ป้องกันแล้ว (ทางเลือก)
หากองค์กรของคุณกำหนดให้ต้องเปลี่ยนรหัสผ่านเป็นระยะ คุณสามารถอัปเดตข้อมูลประจำตัวโดยไม่ต้องรวมไฟล์ใหม่
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);
}
ประเด็นสำคัญ:
- โหลด PDF ที่ป้องกันด้วยรหัสผ่านปัจจุบัน
updatePasswordแทนที่ด้วยรหัสผ่านใหม่- การดำเนินการนี้เร็วเพราะไม่ต้องประมวลผลเนื้อหา PDF ใหม่
การประยุกต์ใช้ในโลกจริง
ฉันเจอปัญหานี้เมื่อต้องรวมสัญญานักลงทุนห้าฉบับที่แต่ละฉบับมีรหัสผ่านของผู้ตรวจสอบคนต่างกัน ด้วยขั้นตอนข้างต้น ฉันถอดรหัสไฟล์ทั้งหมด, รวมเป็นโฟลเดอร์เดียว, และใส่รหัสผ่านเดียวที่สอดคล้องกับนโยบายบริษัท ทั้งกระบวนการใช้เวลาน้อยกว่าสองนาทีบนแล็ปท็อปมาตรฐาน
แนวทางปฏิบัติที่ดีที่สุด
- ตรวจสอบรหัสผ่านตั้งแต่ต้น: ใช้
isDocumentProtectedเพื่อระบุไฟล์ที่อาจต้องการการตรวจสอบด้วยมือ - จำกัดการใช้หน่วยความจำ: สำหรับ PDF ขนาดใหญ่ ควรสตรีมลงดิสก์แทนการเก็บอาเรย์ไบต์ทั้งหมดในหน่วยความจำ
- Dispose วัตถุโดยเร็ว: คลาส Merger ถือทรัพยากรเนทีฟ; ควรเรียก
dispose()ในบล็อกfinallyเสมอ - ใช้ใบอนุญาตชั่วคราว เฉพาะการพัฒนา; ควรขอใบอนุญาตผลิตภัณฑ์ก่อนนำไปใช้งานจริง
สรุป
GroupDocs.Merger for Java ให้ API ที่สะอาดสำหรับการถอดรหัส, การรวม, และการปกป้อง PDF อีกครั้ง โดยทำตามสี่ขั้นตอน—ตรวจจับการป้องกัน, ถอดรหัส, รวมด้วยรหัสผ่านเดียว, และหากต้องการก็เปลี่ยนรหัสผ่าน—คุณสามารถอัตโนมัติกระบวนการสร้างโฟลเดอร์ PDF ที่ปลอดภัยโดยไม่ต้องทำด้วยมือ
ขั้นตอนต่อไป:
- สำรวจตัวเลือกเพิ่มเติมเช่นการตั้งค่าเมตาดาต้า PDF หลังการรวม (เอกสาร)
- เรียนรู้วิธีรวม PDF พร้อมคงบู๊กมาร์ก (อ้างอิง API)
- ดูตัวอย่างโครงการเต็มบน GitHub สำหรับการใช้งานที่พร้อมรัน