Introduction

เมื่อแผนกกฎหมายได้รับ PDF สัญญาหลายไฟล์ แต่ละผู้ตรวจสอบมักจะเพิ่มรหัสผ่านของตนเองเพื่อปกป้องข้อกำหนดที่เป็นความลับ การรวมไฟล์เหล่านี้เป็นแฟ้มเดียวกลายเป็นเรื่องน่าสะพรึงกลัว เพราะรหัสผ่านต่างกันและไฟล์ไม่สามารถรวมโดยตรงได้ การถอดรหัสด้วยมือใช้เวลานานและเสี่ยงต่อข้อผิดพลาด โดยเฉพาะเมื่อต้องจัดการกับหลายสิบไฟล์ PDF

Password‑merge คือเวิร์กโฟลว์ของ GroupDocs.Merger สำหรับ Java ที่ปลดล็อก PDF ที่มีความหลากหลายและปกป้องผลลัพธ์ที่รวมแล้วด้วยข้อมูลรับรองเดียวกัน บทเรียนนี้จะอธิบายขั้นตอนการตรวจจับ PDF ที่มีการป้องกัน การปลดล็อก การรวมเนื้อหา และการหมุนรหัสผ่านที่รวมไว้ (ถ้าต้องการ)

คุณจะได้เรียนรู้วิธีกำหนดค่า Merger API การประมวลผลสตรีมไบต์ และการสร้าง PDF ที่รวมกันอย่างปลอดภัยด้วยโค้ด Java ไม่เกิน 30 บรรทัด

When should I merge password‑protected PDFs?

การรวม PDF ที่มีรหัสผ่านเป็นประโยชน์เมื่อคุณต้องการคลังข้อมูลเดียวที่สามารถค้นหาได้และสอดคล้องกับนโยบายความปลอดภัย พร้อมกับลดภาระการจัดการรหัสผ่านหลายชุด สถานการณ์ทั่วไปได้แก่ ชุดรายงานการเงินรายไตรมาส, แฟ้มสัญญาสำหรับการตรวจสอบ, และไฟล์คดีทางกฎหมายที่ผู้ร่วมทำแต่ละคนใช้รหัสผ่านต่างกัน โดยการปลดล็อกแต่ละไฟล์ด้วยโปรแกรมและใส่รหัสผ่านเดียว คุณจะรักษาความปลอดภัยของคลังข้อมูลและทำให้กระบวนการตรวจสอบต่อไปง่ายขึ้น การดำเนินการทั้งหมดสามารถทำอัตโนมัติใน CI pipeline เพื่อประหยัดเวลาทำงานหลายชั่วโมง

Prerequisites

  • Java 11 หรือใหม่กว่า
  • GroupDocs.Merger for Java 24.6+ (temporary license)
  • ชุดไฟล์ PDF, แต่ละไฟล์อาจมีรหัสผ่านที่สอดคล้องกันหรือไม่มี
mvn dependency:copy -Dartifact=com.groupdocs:groupdocs-merger:24.6

Step 1 – Detect if a PDF is password‑protected

ก่อนที่จะพยายามปลดล็อกไฟล์ ให้ตรวจสอบว่ามีรหัสผ่านหรือไม่ การทำเช่นนี้ช่วยหลีกเลี่ยงการประมวลผลที่ไม่จำเป็นและทำให้คุณบันทึกไฟล์ที่ต้องการข้อมูลรับรอง

// 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:

  • LoadOptions ถือรหัสผ่านที่ทราบไว้; หากไม่มีการระบุไฟล์จะเปิดตามปกติ
  • isPasswordSet() คืนค่า true ทั้งสำหรับรหัสผ่านเจ้าของและผู้ใช้
  • ควรทำการ dispose อินสแตนซ์ Merger เสมอเพื่อปล่อยทรัพยากรเนทีฟ

Step 2 – Unlock each PDF and collect raw bytes

วนลูปผ่านแผนที่ที่คีย์เป็นเส้นทางไฟล์และค่าคือรหัสผ่านของไฟล์นั้น (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;
}

Key points:

  • removePassword() ลบการป้องกันที่มีอยู่
  • เนื้อหาที่ถอดรหัสจะถูกเขียนลงใน ByteArrayOutputStream เพื่อการจัดการในหน่วยความจำ
  • ไฟล์ที่ไม่มีรหัสผ่านจะถูกอ่านโดยตรงเพื่อให้กระบวนการง่ายขึ้น

Step 3 – Merge the unlocked PDFs and apply a unified password

สร้าง 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);
}

Key points:

  • addPassword เข้ารหัส PDF สุดท้ายด้วยข้อมูลรับรองที่ระบุ
  • ทุกการดำเนินการเกิดขึ้นในหน่วยความจำ; มีเพียงไฟล์สุดท้ายที่บันทึกลงดิสก์
  • ทำการ dispose Merger เพื่อปล่อยแฮนด์เดิลเนทีฟ

Step 4 – Rotate the password on an already‑protected PDF (optional)

หากองค์กรของคุณกำหนดให้ต้องหมุนรหัสผ่านเป็นระยะ คุณสามารถอัปเดตข้อมูลรับรองได้โดยไม่ต้องรวมไฟล์ต้นฉบับใหม่

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:

  • โหลด PDF ที่ป้องกันด้วยรหัสผ่านปัจจุบัน
  • updatePassword แทนที่ด้วยข้อมูลรับรองใหม่
  • การดำเนินการนี้เร็วเพราะไม่ต้องประมวลผลเนื้อหา PDF ใหม่

Real‑World Application

ฉันเจอปัญหานี้เมื่อต้องรวมสัญญานักลงทุนห้าฉบับที่แต่ละฉบับมีรหัสผ่านผู้ตรวจสอบต่างกัน ด้วยขั้นตอนข้างต้น ฉันปลดล็อกไฟล์ทั้งหมด รวมเป็นแฟ้มเดียว และใส่รหัสผ่านเดียวที่สอดคล้องกับนโยบายของบริษัท กระบวนการทั้งหมดใช้เวลาน้อยกว่าสองนาทีบนแล็ปท็อปมาตรฐาน

Best Practices

  • Validate passwords early: ใช้ isDocumentProtected เพื่อระบุไฟล์ที่อาจต้องการการตรวจสอบด้วยมือ
  • Limit memory usage: สำหรับ PDF ขนาดใหญ่ ให้สตรีมไปยังดิสก์แทนการเก็บอาร์เรย์ไบต์ทั้งหมดในหน่วยความจำ
  • Dispose objects promptly: คลาส Merger ถือทรัพยากรเนทีฟ; ควรเรียก dispose() ในบล็อก finally เสมอ
  • Use a temporary license only for development; obtain a production license before release.

Conclusion

GroupDocs.Merger for Java ให้ API ที่เรียบง่ายสำหรับการปลดล็อก, การรวม, และการปกป้อง PDF อีกครั้ง การทำตามสี่ขั้นตอน—ตรวจจับการป้องกัน, ปลดล็อก, รวมด้วยรหัสผ่านเดียว, และอาจหมุนรหัสผ่านนั้น—คุณสามารถอัตโนมัติการสร้างแฟ้ม PDF ที่ปลอดภัยโดยไม่ต้องทำด้วยมือ

Next steps:

  • สำรวจตัวเลือกเพิ่มเติม เช่น การตั้งค่าเมตาดาต้า PDF หลังการรวม (documentation).
  • เรียนรู้วิธีรวม PDF พร้อมคงบู๊กมาร์ก (API reference).
  • ดูโครงการตัวอย่างเต็มบน GitHub สำหรับการใช้งานที่พร้อมรัน

Additional Resources