บทนำ

เมื่อแผนกกฎหมายได้รับ 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 สุดท้ายด้วยข้อมูลประจำตัวที่ระบุ
  • ทุกอย่างทำในหน่วยความจำ; มีเพียงไฟล์ผลลัพธ์สุดท้ายที่เขียนลงดิสก์
  • dispose Merger เพื่อปล่อยแฮนด์เนิลเนทีฟ

ขั้นตอนที่ 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 สำหรับการใช้งานที่พร้อมรัน

แหล่งข้อมูลเพิ่มเติม