💡 ตัวอย่างทำงานเต็มที่พร้อมใช้งานบน GitHub:
compare-encrypted-pdf-and-word-documents-dotnet

วิธีเดิมทำให้เจ็บปวด

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

มีเวอร์ชันที่สองของปัญหาเดียวกันที่ง่ายต่อการมองข้าม ทีมบางทีมข้ามโฟลเดอร์ชั่วคราวและถอดรหัสลงในหน่วยความจำแทน ซึ่งแก้ปัญหาการทำความสะอาดได้แต่ไม่แก้ปัญหารูปแบบ: API การถอดรหัสแตกต่างกันตามรูปแบบ ดังนั้นการสนับสนุนสเปรดชีตที่เข้ารหัสหลังจาก PDF ที่เข้ารหัสหมายถึงการบูรณาการครั้งที่สองแทนที่จะเป็นบรรทัดโค้ดที่สอง

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

ค่าใช้จ่ายจริงของการเบี่ยงเบนการถอดรหัส: ไดเรกทอรีชั่วคราวที่เก็บสำเนาข้อความธรรมดาของเอกสารที่ถูกเข้ารหัสด้วยเหตุผลบางอย่าง พร้อมการทำความสะอาดที่ต้องถูกต้องในทุกเส้นทางข้อผิดพลาด

มีวิธีที่ดีกว่า

การเปรียบเทียบที่ป้องกันด้วยรหัสผ่านเป็นความสามารถของ GroupDocs.Comparison สำหรับ .NET ที่เปิดไฟล์ PDF, DOCX, XLSX และ PPTX ที่เข้ารหัสโดยตรงและกำหนดว่ารหัสผ่านใดจะปกป้องผลลัพธ์การเปรียบเทียบ ไม่ต้องมีขั้นตอนการถอดรหัส ไม่ต้องมีตัวกลางเป็นข้อความธรรมดา: รหัสผ่านเดินทางพร้อมเอกสารเข้าสู่การเปรียบเทียบเอง เป็นคุณสมบัติบน LoadOptions

ก่อนที่เราจะเริ่ม คุณจะต้องมี:

  • .NET 8.0 SDK หรือใหม่กว่า
  • GroupDocs.Comparison 26.9.0 (temporary licence)
  • เอกสารที่เข้ารหัสสองไฟล์ที่มีรูปแบบเดียวกันและรหัสผ่านของพวกมัน

ติดตั้งด้วยคำสั่งเดียว:

dotnet add package GroupDocs.Comparison

วิธีใหม่: เอกสารที่เข้ารหัสโดยตรงเข้าสู่ Comparer

ตัวอย่างด้านล่างเปรียบเทียบ PDF ที่เข้ารหัสสองไฟล์ – แหล่งเปิดด้วย 1234 และเป้าหมายเปิดด้วย 4321 – แล้วเขียนไฟล์ผลลัพธ์เดียวที่รวมการเปลี่ยนแปลงไว้ในบรรทัดเดียว รหัสผ่านที่ต่างกันโดยเจตนา เพราะนั่นคือที่ซ่อนข้อผิดพลาดแรก

ขั้นตอนที่ 1 - ให้แต่ละเอกสารมี LoadOptions ของตนเอง

Comparer ถือแหล่งเดียวและเป้าหมายได้หลายไฟล์ และแต่ละเอกสารมีการป้องกันของตนเอง รหัสผ่านของแหล่งจะส่งไปยังคอนสตรัคเตอร์; รหัสผ่านของแต่ละเป้าหมายจะส่งไปยังการเรียก Add ของมันเอง

// One LoadOptions per document - the constructor's options unlock the
// source only, and never reach the targets.
using var comparer = new Comparer("source.pdf",
    new LoadOptions { Password = "1234" });
comparer.Add("target.pdf", new LoadOptions { Password = "4321" });

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

ขั้นตอนที่ 2 - ตัดสินใจว่าอะไรจะปกป้องผลลัพธ์

CompareOptions.PasswordSaveOption เลือกการปกป้องของผลลัพธ์: None, Source, Target หรือ User ค่าเริ่มต้นคือ None ซึ่งจะเปลี่ยนอินพุตที่เข้ารหัสสองไฟล์ให้กลายเป็นผลลัพธ์ที่ไม่มีการปกป้องอย่างเงียบ ๆ

// Inline markup, and the result reuses the source document's password.
var options = new PdfCompareOptions
{
    DisplayMode = PdfCompareOptions.ComparisonDisplayMode.Inline,
    PasswordSaveOption = PasswordSaveOption.Source
};

comparer.Compare("Result/1-pdf-inline.pdf", options);

จุดสำคัญ:

  • PasswordSaveOption: Source ใช้รหัสผ่านของแหล่งบนผลลัพธ์ เลือก User พร้อม SaveOptions.Password เพื่อกำหนดรหัสผ่านใหม่แทน
  • ComparisonDisplayMode: อยู่ภายใน PdfCompareOptions ซึ่งยังมี SideBySide และ Interleaved WordCompareOptions ประกาศ enum ชื่อเดียวกันแต่ค่าต่างกัน ดังนั้นการใช้ชื่อโดยไม่มีการระบุประเภทจะไม่คอมไพล์ – ต้องระบุเต็ม

ขั้นตอนที่ 3 - ปกป้องผลลัพธ์ด้วยรหัสผ่านของมันเอง

เมื่อ diff ถูกส่งให้ผู้ตรวจสอบที่ไม่ควรถือรหัสผ่านต้นฉบับใด ๆ PasswordSaveOption.User จะรับค่าจาก SaveOptions.Password แทนการใช้รหัสผ่านจากอินพุต

var compareOptions = new PdfCompareOptions
{
    DisplayMode = PdfCompareOptions.ComparisonDisplayMode.Inline,
    PasswordSaveOption = PasswordSaveOption.User
};
var saveOptions = new SaveOptions { Password = "5678" };

comparer.Compare("Result/4-own-password.pdf", saveOptions, compareOptions);

อ็อบเจ็กต์ทั้งสองจะถูกส่งไปยังเมธอด Compare ที่รับสามอาร์กิวเมนต์ การตั้งค่า SaveOptions.Password เพียงอย่างเดียวไม่ทำให้เกิดการเปลี่ยนแปลง – ค่าของ enum คือสิ่งที่เปิดใช้งานรหัสผ่านด้านการบันทึก ผลลัพธ์จากการเรียกนี้เปิดด้วย 5678 และปฏิเสธ 1234

ทำไม try/catch รอบ Comparer ของฉันไม่จับรหัสผ่านที่ไม่ถูกต้อง?

เพราะคอนสตรัคเตอร์ไม่เคยเปิดไฟล์เลย มันบันทึกเส้นทางไว้เช่นเดียวกับ Add ทั้งสองไฟล์จะถูกอ่านเมื่อ Compare ทำงาน และที่นั่นจะเกิด PasswordProtectedFileException พร้อมข้อความ Password is missing การใช้รหัสผ่านผิดก็ทำงานเช่นเดียวกัน: ยอมรับโดยเงียบในขั้นตอนการสร้าง แล้วปฏิเสธภายหลังที่ Compare

ดังนั้นให้ป้องกันการเรียกเปรียบเทียบ ไม่ใช่คอนสตรัคเตอร์ ฉันพบวิธีนี้แบบช้าโดยห่อการสร้างใน try แล้วดูไฟล์ที่เข้ารหัสผ่านตรง ๆ ก่อนจะล้มเหลวสามบรรทัดต่อมา รีโพซิทอรีพิมพ์แต่ละขั้นตอน ทำให้ลำดับชัดเจนในการอ่านครั้งแรก:

using var comparer = new Comparer("source.pdf");   // succeeds
comparer.Add("target.pdf");                        // succeeds
comparer.Compare("Result/unreachable.pdf");        // throws here

เปรียบเทียบเคียงกัน: ก่อน vs. หลัง

ก่อน (ถอดรหัสก่อน) หลัง (GroupDocs.Comparison)
ขั้นตอนของกระบวนการ ถอดรหัสทั้งสองไฟล์, เปรียบเทียบ, ลบสำเนาชั่วคราว เปรียบเทียบ
ข้อความธรรมดาบนดิสก์ สำเนาสองไฟล์, ทำความสะอาดในทุกเส้นทางข้อผิดพลาด ไม่มี
การปกป้องผลลัพธ์ ขั้นตอนการเข้ารหัสใหม่แยกต่างหาก ค่า PasswordSaveOption หนึ่งค่า
การครอบคลุมรูปแบบ เครื่องมือถอดรหัสตามรูปแบบ ค่า LoadOptions.Password หนึ่งค่า สำหรับ PDF, DOCX, XLSX, PPTX
โค้ดที่ต้องใช้ ตัวช่วยถอดรหัสบวกการเปรียบเทียบ 4 บรรทัด

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

การจัดชั้นนี้ทำให้การครอบคลุมรูปแบบเป็นเรื่องราคาถูก LoadOptions.Password เป็นคุณสมบัติ string ธรรมดา และคุณสมบัตินี้เดียวกันก็ปลดล็อก PDF, DOCX, XLSX และ PPTX – โค้ดการโหลดในตัวอย่าง Word ด้านล่างเป็นตัวอักษรต่ออักษรกับตัวอย่าง PDF ที่ใช้ เพียงคลาส options ที่เปลี่ยนเท่านั้น และเพราะแต่ละรูปแบบเปิดเผยตัวเลือกการเรนเดอร์ที่แตกต่างกัน การเพิ่มการสนับสนุนสเปรดชีตที่เข้ารหัสให้กับโค้ดที่เปรียบเทียบ PDF ที่เข้ารหัสอยู่แล้วไม่ต้องใช้ค่าใช้จ่ายใด ๆ ในเส้นทางการโหลด

ตัวอย่างจากโลกจริง: การทำเครื่องหมายสัญญาระหว่างบริษัทกฎหมาย

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

สองการตั้งค่าครอบคลุมกรณีนี้ แต่ละเอกสารจะถูกปลดล็อกด้วย LoadOptions ของตนเอง ดังนั้นการหมุนรหัสผ่านไม่ต้องการการจัดการพิเศษ และ PasswordSaveOption.User ให้แต่ละ diff ที่แจกจ่ายมีรหัสผ่านของมันเอง – รหัสผ่านที่ปลดล็อกการเปรียบเทียบและไม่มีอะไรอื่น

// Word revisions, so the reviewing partner can accept or reject each edit.
var options = new WordCompareOptions
{
    DisplayMode = WordCompareOptions.ComparisonDisplayMode.Revisions,
    PasswordSaveOption = PasswordSaveOption.Source
};

using var comparer = new Comparer("round3.docx",
    new LoadOptions { Password = "1234" });
comparer.Add("round4.docx", new LoadOptions { Password = "4321" });
comparer.Compare("Result/redline.docx", options);

คุณสามารถทำอะไรได้อีกกับ GroupDocs.Comparison?

  • เปรียบเทียบมากกว่าสองเอกสารที่ป้องกัน: เพิ่มเป้าหมายที่เข้ารหัสหลายไฟล์ในหนึ่งการเปรียบเทียบ สำหรับรูปแบบ Word และพรีเซนเทชัน
  • สร้าง Revision ของ Word แบบเนทีฟ: WordCompareOptions.ComparisonDisplayMode.Revisions เขียนการเปลี่ยนแปลงที่ผู้ตรวจสอบยอมรับหรือปฏิเสธใน Word เอง
  • ควบคุมการโหลดทรัพยากรภายนอก: บล็อกหรืออนุญาตรายการอ้างอิงระยะไกลที่เอกสารพกพาไว้ อีกหนึ่งการป้องกันด้วย LoadOptions
  • สร้างหน้าสรุป: GenerateSummaryPage เพิ่มภาพรวมการเปลี่ยนแปลงลงในเอกสารผลลัพธ์

สรุป

การเบี่ยงเบนการถอดรหัสไม่เคยเกี่ยวกับการเปรียบเทียบ – มันเกี่ยวกับไลบรารีที่ไม่สามารถอ่านสิ่งที่คุณมี การตั้งค่า LoadOptions.Password ต่อเอกสารแต่ละไฟล์จะลบโฟลเดอร์ชั่วคราว เส้นทางการทำความสะอาด และ diff ที่ไม่มีการปกป้องที่ปลายสาย การตัดสินใจเพียงสามอย่างคือที่เหลือ: รหัสผ่านต่อเอกสาร, PasswordSaveOption ที่ชัดเจนแทนค่าเริ่มต้น None, และการจัดการข้อผิดพลาดรอบ Compare ที่เป็นจุดที่ความล้มเหลวจริง ๆ เกิดขึ้น

พร้อมที่จะอัตโนมัติกระบวนการทำงานเอกสารของคุณหรือยัง?

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