💡 ตัวอย่างทำงานเต็มที่มีบน GitHub: scrub-office-document-pii-dotnet
วิธีเดิมทำให้เจ็บปวด
ขั้นตอนเป็นแบบนี้ เปิดเอกสาร, File, Info, Check for Issues, Inspect Document, ทำเครื่องหมายในช่องต่าง ๆ, Remove All, บันทึกเป็นชื่อใหม่, ปิด, เปิดไฟล์ต่อไป อีกสี่สิบไฟล์หลังจากนั้นมีคนสังเกตว่า Inspect Document ยังลบ Title ที่ระบบบันทึกดัชนีคีย์ไว้ด้วย, และไฟล์ที่ส่งออกไปหนึ่งชั่วโมงก่อนยังคงมี SharePoint approver ID อยู่, เพราะไฟล์นั้นถูกบันทึกจากแอปพลิเคชันอื่นที่เขียนฟิลด์นั้นกลับมา
การลบ Metadata PII เป็นความสามารถของ GroupDocs.Metadata สำหรับ .NET ที่ลบคุณสมบัติที่บรรจุข้อมูลส่วนบุคคลจากเอกสาร Office อย่างโปรแกรมและรายงานสิ่งที่เหลืออยู่หลังจากนั้น ขั้นตอนแบบแมนนวลล้มเหลวในสามประการ: ไม่สามารถขยายได้เกินจำนวนไฟล์ไม่กี่ไฟล์, เป็นแบบทั้งหมดหรือไม่มีเลยว่า ฟิลด์ใดจะถูกลบ, และไม่สร้างบันทึกของสิ่งที่ถูกลบ บทความนี้แสดงเวอร์ชัน .NET ของงานเดียวกัน, ทีละกลุ่มคุณสมบัติ
การรู้ว่ามีอะไรอยู่ในนั้นจริง ๆ จะช่วยได้ ไฟล์ Word ที่ผ่านการตรวจทานมักจะมี Author และ LastSavedBy จากบัญชี Windows ของผู้ที่บันทึก, Manager และ Company จากเทมเพลตองค์กร, ตัวนับการแก้ไข, TotalEditingTime, timestamp LastPrinted, และตัวนับสำหรับเธรดคอมเมนต์ เพิ่ม SharePoint เข้าไปในห่วงโซ่แล้วคุณจะได้ตัวระบุผู้อนุมัติ, เส้นทาง workflow, URI ของ content‑type, และเทมเพลตที่เอกสารถูกสร้างจาก ไม่มีอย่างใดที่มองเห็นบนหน้า, และทั้งหมดนั้นเดินทางอยู่ในไฟล์เดียวกัน
มีวิธีที่ดีกว่า
ทุกอย่างใน GroupDocs.Metadata สำหรับ .NET ทำงานผ่านเครื่องมือค้นหาคุณสมบัติเดียว RemoveProperties รับ lambda ที่ทำงานกับ MetadataProperty, ลบทุกคุณสมบัติที่ lambda ยอมรับ, และคืนค่าจำนวนที่ลบ FindProperties ทำงานด้วย lambda เดียวกันแต่ไม่เขียนลงไฟล์ คุณสมบัติมีแท็กด้วย, ดังนั้น Tags.Person.Creator ระบุฟิลด์สไตล์ผู้เขียนข้ามรูปแบบและแพ็กเกจแทนการจับคู่ชื่อที่แตกต่างกันตามแอปพลิเคชันที่สร้าง
นั่นให้รูปแบบการทำความสะอาดสามแบบแทนการกดปุ่มเดียว: การผ่านแท็กสำหรับฟิลด์อัตลักษณ์, การผ่านชื่อสำหรับกลุ่มเช่นคอมเมนต์และการแก้ไข, และ Sanitize() เมื่อไม่ต้องการให้สิ่งใดเหลืออยู่ ทั้งสามคืนค่าตัวเลข, และตัวเลขคือสิ่งที่ทำให้การผ่านนั้นตรวจสอบได้
วิธีใหม่: Predicate ต่อกลุ่มคุณสมบัติ
ขั้นตอนที่ 1 - ลบชื่อ
การตรวจสอบแท็กสี่อย่างครอบคลุมกลุ่มอัตลักษณ์ ฟิลด์เชิงบรรยายจะไม่ถูกแตะต้อง, ซึ่งต่างจาก Document Inspector’s Remove All:
using (var metadata = new Metadata(inputPath))
{
if (metadata.FileFormat == FileFormat.Unknown) return 0;
var affected = metadata.RemoveProperties(p =>
p.Tags.Contains(Tags.Person.Creator) ||
p.Tags.Contains(Tags.Person.Editor) ||
p.Tags.Contains(Tags.Person.Manager) ||
p.Tags.Contains(Tags.Corporate.Company));
metadata.Save(outputPath);
return affected;
}
การตรวจสอบ FileFormat.Unknown เป็นการป้องกันที่ทำให้ค่า 0 ซื่อสัตย์: หากไม่มีการตรวจสอบนี้, ไฟล์ที่อ่านไม่ได้และไฟล์ที่สะอาดจะดูเหมือนกันต่อผู้เรียกใช้
ขั้นตอนที่ 2 - ลบกลุ่มที่เกี่ยวข้อง
คอมเมนต์, การแก้ไข, และฟิลด์เซิร์ฟเวอร์ไม่มีแท็ก, ดังนั้น predicate จะจับชื่อแทน เส้นเวลาการแก้ไขเป็นกลุ่มที่มักถูกลืมที่สุด, และเป็นกลุ่มที่บอกว่าเอกสารถูกสร้างอย่างไร:
using (var metadata = new Metadata(inputPath))
{
if (metadata.FileFormat == FileFormat.Unknown) return 0;
var affected = metadata.RemoveProperties(p =>
p.Name != null && (
p.Name.Contains("Revision") ||
p.Name.Contains("TrackedChange") ||
p.Name.Contains("LastPrinted") ||
p.Name.Contains("TotalEditingTime") ||
p.Name.Contains("EditTime")));
metadata.Save(outputPath);
return affected;
}
การจับคู่ส่วนย่อยเป็นเจตนา: มันจะจับ CommentsCount พร้อมกับ Comment, และ TotalEditingTime พร้อมกับ EditTime โดยไม่ต้องดูแลรายการชื่อที่แม่นยำต่อรูปแบบ SharePoint pass คือการเรียกเดียวกันกับ Server, Workflow, Approver, ContentType, และ Template
ขั้นตอนที่ 3 - ลบทุกอย่าง, แล้วตรวจสอบผลลัพธ์
ที่ขอบเขตความเชื่อถือ, การเรียกเดียวแทนที่สี่การผ่าน:
using (var metadata = new Metadata(inputPath))
{
if (metadata.FileFormat == FileFormat.Unknown) return 0;
var affected = metadata.Sanitize();
metadata.Save(outputPath);
return affected;
}
จากนั้นส่วนที่ขั้นตอนแมนนวลไม่มีเทียบเท่า การสแกนตรวจสอบใช้ predicate การลบผ่าน FindProperties และจัดเรียงสิ่งที่เหลือเป็นสองรายการ:
foreach (var p in props)
{
var value = p.InterpretedValue?.ToString() ?? p.Value?.ToString() ?? string.Empty;
if (string.IsNullOrWhiteSpace(value)) continue;
if (value == "0" || value == "0.0") continue;
var entry = $"{p.Name}={value}";
var name = p.Name ?? string.Empty;
if (name.StartsWith("Comment") || name.StartsWith("Revision"))
report.ContentLevelLeaks.Add(entry);
else
report.MetadataLeaks.Add(entry);
}
MetadataLeaks ต้องว่างเปล่าก่อนที่ไฟล์จะถือว่าได้รับการทำความสะอาด ContentLevelLeaks เป็นข้อมูลเชิงบรรยาย: คอมเมนต์ Word และผู้เขียนการเปลี่ยนแปลงที่ติดตามอยู่ใน word/document.xml, ซึ่งเป็นเนื้อหาใน body, และการลบสิ่งเหล่านี้ต้องใช้ไลบรารีการแก้ไขเนื้อหาเช่น Aspose.Words แทน API metadata
ทำไมไม่เรียก Sanitize() กับทุกอย่างเลย?
เพราะเอกสารส่วนใหญ่ยังคงใช้งานอยู่ Sanitize() ลบทุกแพ็กเกจที่ตรวจพบ, รวมถึง Title, Subject, และ Keywords, ฟิลด์ที่ระบบบันทึกและดัชนีการค้นหาพึ่งพา ใช้การผ่านที่เจาะจงขณะไฟล์หมุนเวียนภายในองค์กร, ให้ metadata เชิงบรรยายทำงาน, และเก็บการลบทั้งหมดไว้สำหรับสำเนาที่ออกจากองค์กรจริง
การเปรียบเทียบข้างเคียง: ก่อน vs. หลัง
| การตรวจสอบด้วยมือ | GroupDocs.Metadata สำหรับ .NET | |
|---|---|---|
| ความเลือกได้ | Remove All, รวมฟิลด์เชิงบรรยาย | predicate หนึ่งต่อกลุ่มคุณสมบัติ |
| ความครอบคลุม | ฟิลด์ที่ไดอะล็อกแสดง | ทุกแพ็กเกจที่ไลบรารีตรวจพบ, รวมส่วน OOXML ที่กำหนดเอง |
| บันทึก | ไม่มี | จำนวนที่ได้รับผลกระทบคืนต่อการดำเนินการ |
| การตรวจสอบ | เปิดใหม่และดู | การสแกน FindProperties พร้อมรายการ metadata และระดับเนื้อหา |
| งานชุด 200 ไฟล์ | 200 ครั้งคลิก | ลูปเดียว, ห้าการดำเนินการ, บรรทัดบันทึกหนึ่งต่อไฟล์ |
แถวที่เปลี่ยนพฤติกรรมคือบันทึก เมื่อทุกการผ่านคืนค่าจำนวน, การทำความสะอาดจะไม่ใช่ขั้นตอนที่ใครต้องจำทำแล้ว, แต่กลายเป็นข้อมูลที่ pipeline สามารถอ้างอิงได้: เกณฑ์ในเทสต์, ฟิลด์ในตาราง audit, เงื่อนไขที่ทำให้งานประจำคืนล้มเหลว นั่นคือแถวที่ขั้นตอนแมนนวลไม่สามารถผลิตได้ในระดับวินัยใด ๆ
ตัวอย่างจากโลกจริง: Hook ก่อนส่ง
พอร์ทัลสนับสนุนให้พนักงานแนบเอกสารกับทิกเก็ตลูกค้า ตัวจัดการแนบไฟล์ตอนนี้รันการผ่านอัตลักษณ์และการผ่านเซิร์ฟเวอร์ก่อนที่ไฟล์จะถูกจัดเก็บ, บันทึกจำนวนทั้งสองต่อทิกเก็ต, และรันการตรวจสอบการรั่วไหลบนสำเนาที่บันทึกไว้ รายการ metadata‑leak ที่ไม่ว่างเปล่าจะปฏิเสธการอัปโหลดพร้อมข้อความระบุฟิลด์ที่เป็นปัญหา, ดังนั้นผู้ที่แนบไฟล์จะทราบทันทีแทนที่จะรู้หลังจากไฟล์ถึงมือลูกค้า
สองรายละเอียดทำให้ hook นี้ใช้งานได้จริง การผ่านเขียนไปยังเส้นทางใหม่, ดังนั้นไฟล์ต้นฉบับยังคงอยู่ในที่เก็บของพนักงานและไม่มีอะไรถูกทำลายโดยขั้นตอนอัตโนมัติ และจำนวนเหล่านั้นจะถูกบันทึกในบันทึกทิกเก็ตข้างไฟล์แนบ, ซึ่งหมายความว่าคำตอบของ “อะไรถูกลบจากเอกสารนี้” คือจำนวนที่เก็บไว้แทนการสันนิษฐานว่าท่อการทำงานทำอะไรบ่อย ๆ
ครั้งแรกที่ฉันชี้ตรวจสอบนี้ที่เทมเพลตจริง, มันกลับมาพร้อมค่า Manager ที่การผ่านอัตลักษณ์ได้ลบไปเมื่อวินาทีก่อนและเทมเพลตองค์กรได้เขียนกลับเมื่อบันทึก การเรียกลบทำงานตามเอกสาร, แต่ท่อการทำงานรอบ ๆ มันคือปัญหา, และเพียงการอ่านกลับเท่านั้นที่แสดงให้เห็น
คุณสามารถทำอะไรได้อีกกับ GroupDocs.Metadata?
เครื่องยนต์ predicate เดียวกันสามารถอ่านได้ การเปรียบเทียบคุณสมบัติระหว่างสองเวอร์ชันของเอกสารเปิดเผยการเปลี่ยนแปลงเจ้าของและการเขียนใหม่นอกกระบวนการตรวจทาน, และ metadata scrubbing overview ครอบคลุมว่าตัวเครื่องมือเชิงโต้ตอบยังคงเข้ากันได้อย่างไรกับการผ่านแบบ API‑driven เนื่องจากระบบแท็กครอบคลุมหลายรูปแบบ, predicate อัตลักษณ์ที่เขียนที่นี่ยังทำงานกับ PDF, รูปภาพ, และไฟล์เสียงโดยไม่ต้องแก้ไข
ความพกพานั้นคุ้มค่าที่จะวางแผนไว้ กฎการทำความสะอาดที่เขียนเป็น lambda บน MetadataProperty เป็น C# ธรรมดา, ดังนั้นมันสามารถอยู่ในไลบรารีที่ใช้ร่วมกัน, ทดสอบหน่วยกับเอกสาร fixture, และนำไปใช้โดยบริการใดก็ได้ที่ต้องการ: endpoint ส่งออก, งานบันทึกตามกำหนด, หรือขั้นตอน build ที่ทำความสะอาดไฟล์แนบเอกสารก่อนปล่อย กฎจะอยู่ที่เดียว; เพียงจุดเรียกใช้ที่เปลี่ยน
สรุป
สี่การผ่านที่เจาะจง, หนึ่งการทำความสะอาดเต็ม, หนึ่งการสแกนตรวจสอบ ชุดนี้ครอบคลุมช่วงการใช้งานจริงสำหรับเอกสาร Office: รักษา metadata เชิงบรรยายขณะไฟล์อยู่ในวงจร, ลบทุกอย่างเมื่อไฟล์ออกจากองค์กร, และพิสูจน์ผลลัพธ์ในทุกกรณี คัดลอกตัวอย่าง, รันกับเอกสารที่ผ่านการตรวจทานจริง, และอ่านจำนวนที่ได้รับผลกระทบ จำนวนเหล่านี้มักจะสูงกว่าที่คาด, ซึ่งเป็นจุดประสงค์ทั้งหมด