💡 ตัวอย่างการทำงานเต็มที่พร้อมใช้งานบน GitHub:
office-metadata-pii-cleanup-nodejs
บทนำ
จุดเชื่อมต่ออัปโหลดรับไฟล์ DOCX จากพนักงานและเก็บไว้ในตั๋วของลูกค้า ข้อความในไฟล์ไม่มีปัญหา แต่คุณสมบัติของไฟล์กลับมีปัญหา: ไฟล์บันทึกชื่อผู้ร่าง, เพื่อนร่วมงานที่บันทึกล่าสุด, ผู้จัดการแผนกจากเทมเพลตองค์กร, และเนื่องจากไฟล์มาจาก SharePoint จึงบันทึกชื่อผู้อนุมัติที่เซ็นรับรอง
ตัวทำความสะอาด metadata คือสคริปต์เล็ก ๆ ที่ลบคุณสมบัติเหล่านั้นก่อนที่ไฟล์จะถูกเก็บและจากนั้นตรวจสอบผลการทำงานของตนเอง บทแนะนำนี้สร้างสคริปต์ดังกล่าวใน Node.js ด้วย GroupDocs.Metadata ในสี่ขั้นตอน: เลือกคุณสมบัติตามแท็ก, เลือกตามชื่อ, ลบทุกอย่างเมื่อการเลือกอย่างเจาะจงไม่ช่วยแล้ว, และตรวจสอบสิ่งที่เหลืออยู่ แต่ละขั้นตอนใช้เพียงไม่กี่บรรทัดและสคริปต์ที่เสร็จสมบูรณ์มีความยาวน้อยกว่าหนึ่งร้อยบรรทัด
ทำไมการทำความสะอาด Metadata ถึงสำคัญ
ข้อมูลสะสมโดยที่ไม่มีใครเลือกให้ Word จะเขียน Author และ LastSavedBy จากบัญชีระบบปฏิบัติการทุกครั้งที่บันทึก, เก็บตัวนับการแก้ไข, ติดตาม TotalEditingTime, และบันทึก LastPrinted เซิร์ฟเวอร์เอกสารจะเพิ่มเส้นทางการทำงาน, ตัวระบุผู้อนุมัติ, และ URI ของประเภทเนื้อหาเมื่อทำการเช็คอิน สิ่งเหล่านี้ไม่ปรากฏเมื่ออ่านหรือพิมพ์เอกสาร ดังนั้นการตรวจทานก็ไม่สามารถจับได้
เหตุผลที่ทำใน Node.js แทนการทำด้วยมือคือสคริปต์จะคืนค่าตัวเลข: การเรียกลบแต่ละครั้งจะรายงานจำนวนคุณสมบัติที่ถูกลบและค่านั้นสามารถบันทึกลงล็อก, ตรวจสอบในเทสต์, หรือแนบไปกับบันทึกที่เอกสารเป็นส่วนหนึ่งได้
มีเหตุผลที่สองที่อาจไม่ชัดเจนจนกว่าจะมีงานแบช งานทำความสะอาดด้วยมือเป็นการตัดสินใจหนึ่งครั้งต่อไฟล์โดยผู้ที่กำลังจัดการไฟล์นั้น ดังนั้นสองคนที่ทำความสะอาดเอกสารประเภทเดียวกันอาจให้ผลลัพธ์ที่ต่างกัน สคริปต์จึงกำหนดกฎไว้ที่เดียว: แท็กสี่แท็กเดียวกัน, รายการสตริงย่อยเดียวกัน, ใช้แบบเดียวกันไม่ว่าจะคิวมีไฟล์สามไฟล์หรือสามพันไฟล์
ข้อกำหนดเบื้องต้น
แพ็กเกจนี้เป็น Node.js ผ่าน Java ดังนั้นเครื่องต้องมี Java runtime ควบคู่กับ Node
การติดตั้ง
npm install @groupdocs/groupdocs.metadata
โครงการตัวอย่างระบุเวอร์ชัน 26.7 และเพิ่มรายการ overrides ที่ตั้งค่า nan เป็น ^2.22.0 ซึ่งทำให้การสร้าง native binding ทำงานได้บน Node เวอร์ชันปัจจุบัน หากไม่มีไฟล์ลิขสิทธิ์ไลบรารีจะทำงานในโหมดประเมินผล ซึ่งเพียงพอสำหรับทำตามทุกขั้นตอนที่นี่
ขั้นตอนที่ 1 - เลือกคุณสมบัติตามความหมายของมัน
ชื่อคุณสมบัติจะแตกต่างกันระหว่างรูปแบบและแพ็กเกจ ดังนั้นกฎแรกจึงจับคู่ตามแท็กแทน ContainsTagSpecification รับแท็กและจับคู่กับคุณสมบัติใด ๆ ที่มีแท็กนั้น; .or() จะรวมสเปคหลาย ๆ ตัวเป็นหนึ่ง
const T = groupdocs.Tags;
const spec = new groupdocs.ContainsTagSpecification(T.getPerson().getCreator())
.or(new groupdocs.ContainsTagSpecification(T.getPerson().getEditor()))
.or(new groupdocs.ContainsTagSpecification(T.getPerson().getManager()))
.or(new groupdocs.ContainsTagSpecification(T.getCorporate().getCompany()));
const affected = metadata.removeProperties(spec);
metadata.save(outputPath);
จุดสำคัญ:
- แท็กสี่แท็กครอบคลุมกลุ่มอัตลักษณ์: creator, editor, manager, และฟิลด์บริษัทขององค์กร
- Title, Subject, และ Keywords ไม่ถูกแก้ไข ดังนั้นดัชนีบันทึกที่อ้างอิงฟิลด์เหล่านี้ยังคงทำงานได้
removePropertiesคืนค่าจำนวนที่ได้รับผลกระทบแทนการคืนค่า boolean
ห่อหุ้มทั้งหมดด้วย try/finally พร้อม metadata.close() ในบล็อก finally การเชื่อมต่อจะเปิดไฟล์ไว้จนกว่าจะปิด และลูปที่ไม่มีการปิดจะทำให้หมด handle
ขั้นตอนที่ 2 - เลือกคุณสมบัติตามชื่อ
กระทู้คอมเมนต์, ตัวนับการแก้ไข, และฟิลด์เซิร์ฟเวอร์ไม่มีแท็ก สำหรับกรณีเหล่านี้ WithNameSpecification(needle, false) จะจับคู่กับคุณสมบัติใด ๆ ที่ชื่อประกอบด้วยสตริงที่ระบุ และบิลเดอร์สี่บรรทัดจะเชื่อมต่อหนึ่งสเปคต่อสตริงย่อย:
let spec = null;
for (const needle of needles) {
const s = new groupdocs.WithNameSpecification(needle, false /* fullMatch */);
spec = spec ? spec.or(s) : s;
}
return spec;
บิลเดอร์นี้ถูกใช้สามครั้งด้วยรายการต่าง ๆ คอมเมนต์เป็นรายการแรก:
const affected = metadata.removeProperties(
nameContainsSpec(['Comment', 'Reviewer', 'Reviewed']));
metadata.save(outputPath);
ไทม์ไลน์การแก้ไขเป็นกลุ่มที่มักถูกลืมและเป็นกลุ่มที่อธิบายวิธีการสร้างเอกสาร:
const affected = metadata.removeProperties(nameContainsSpec([
'Revision', 'TrackedChange', 'LastPrinted', 'TotalEditingTime', 'EditTime',
]));
metadata.save(outputPath);
การผ่านของ SharePoint ใช้การเรียกเดียวกันกับ Server, Workflow, Approver, ContentType, และ Template การจับคู่สตริงย่อยทำโดยเจตนาเพื่อให้จับ CommentsCount พร้อมกับ Comment โดยไม่ต้องดูแลรายการชื่อที่แม่นยำสำหรับแต่ละรูปแบบ
ขั้นตอนที่ 3 - ลบทุกอย่างเมื่อการเลือกอย่างเจาะจงไม่ช่วยแล้ว
สำหรับสำเนาที่ออกจากองค์กร การเรียกครั้งเดียวนี้แทนที่การผ่านสี่ครั้ง:
const affected = metadata.sanitize();
metadata.save(outputPath);
sanitize() จะลบทุกแพ็กเกจ metadata ที่ไลบรารีตรวจพบ รวมถึงส่วน OOXML ที่กำหนดเองด้วย และจำนวนที่คืนมามักจะมากกว่าผลรวมของการผ่านที่เจาะจง มันยังลบ Title และ Subject ด้วยเหตุผลที่ทำให้ต้องใช้ในขั้นตอนสุดท้ายแทนการวนลูปตรวจสอบ
ขั้นตอนที่ 4 - ตรวจสอบ, เพราะการพลาดแบบเงียบดูเหมือนสำเร็จ
การสแกนใช้สเปคเดียวกันผ่าน findProperties ซึ่งอ่านโดยไม่เขียน ผลลัพธ์เป็นคอลเลกชันของ Java จึงต้องวนด้วยดัชนี:
const props = metadata.findProperties(tagSpec.or(nameSpec));
for (let i = 0; i < props.getCount(); i++) {
const p = props.get_Item(i);
const val = p.getValue && p.getValue();
const value = val ? String(val.getRawValue ? val.getRawValue() : val) : '';
if (!value || value === '0' || value === '0.0') continue;
leaks.push(`${p.getName()}=${value}`);
}
ตัวกรองค่าว่างและศูนย์ได้รับการใส่ไว้ด้วยเหตุผล ฉันเพิ่มมันหลังจากการรันล้มเหลวเนื่องจากตัวนับการแก้ไขถูกล้างเป็น 0 ซึ่งการสแกนรายงานเป็นคุณสมบัติที่ยังคงอยู่อย่างตรงไปตรงมา
ตัวอย่างการทำงานเต็ม
รีโพซิทอรีเชื่อมต่อฟังก์ชันหกตัวเข้ากับ index.js ซึ่งใช้ลิขสิทธิ์, รันแต่ละการผ่านกับ resources/pii-sample.docx, ตรวจสอบว่าไฟล์ผลลัพธ์ทุกไฟล์มีอยู่, และสรุปด้วยการตรวจสอบว่ารายการรั่วไม่มีรายการใด ๆ การตรวจสอบที่ล้มเหลวจะออกด้วยรหัสไม่เป็นศูนย์ ดังนั้นทั้งหมดทำงานเป็นการตรวจสอบใน CI แทนการเป็นสาธิตที่คุณอ่าน
รายละเอียดหนึ่งที่ควรคัดลอกไปใช้ในเวอร์ชันของคุณ: แต่ละการผ่านอ่านไฟล์ต้นฉบับเดียวกันและเขียนผลลัพธ์แยกไฟล์ ไม่ได้ต่อเนื่องไฟล์ที่ทำความสะอาดแล้วไปยังการผ่านต่อไป วิธีนี้ทำให้จำนวนที่ได้รับผลกระทบเป็นอิสระกัน ดังนั้นบรรทัดล็อกของการผ่านคอมเมนต์จะแสดงสิ่งที่กฎคอมเมนต์พบ ไม่ใช่สิ่งที่เหลือหลังจากกฎอัตลักษณ์ทำงาน
เมื่อใดที่ควรรันการผ่านแบบเจาะจงแทนการใช้ sanitize()?
เมื่อใดก็ตามที่เอกสารถูกใช้งานอยู่ ไฟล์ที่หมุนเวียนระหว่างผู้ตรวจสอบพึ่งพา Title, Subject, และ Keywords สำหรับการค้นหาและการจัดประเภท และ sanitize() จะลบทั้งสามพร้อมกับข้อมูลส่วนบุคคล รันการผ่านอัตลักษณ์และคอมเมนต์ระหว่างการทำงานร่วมกันเพื่อรักษาฟิลด์อธิบายไว้ครบถ้วน และเก็บการลบทั้งหมดไว้สำหรับสำเนาที่ออกจากองค์กรจริง
การประยุกต์ใช้ในโลกจริง
ตัวจัดการการอัปโหลด
เส้นทาง Express ทำความสะอาดไฟล์แนบก่อนบันทึกลงที่เก็บ, บันทึกจำนวนที่ได้รับผลกระทบในตั๋ว, และปฏิเสธการอัปโหลดเมื่อรายการรั่วไม่ว่างเปล่า
งานส่งออกประจำคืน
เวิร์กเกอร์เดินสำรวจโฟลเดอร์ส่งออก, ใช้การผ่านอัตลักษณ์และเซิร์ฟเวอร์, และทำให้งานล้มเหลวแทนการบันทึกคำเตือนเมื่อเอกสารยังรายงาน PII ที่เหลืออยู่
ประตูก่อนการเผยแพร่
ขั้นตอนการสร้างทำความสะอาดไฟล์แนบเอกสารก่อนการปล่อย, ใช้ sanitize() เนื่องจากไม่มีข้อมูลใดในไฟล์เหล่านั้นที่ต้องการรักษา metadata ไว้
แนวปฏิบัติที่ดีที่สุดและเคล็ดลับ
- เขียนเสมอไปยังเส้นทางใหม่เพื่อให้ไฟล์ต้นฉบับยังคงอยู่สำหรับการแก้ไขข้อโต้แย้ง
- ปิดวัตถุ metadata ในบล็อก
finallyโดยเฉพาะในลูป - รวมสเปคด้วย
.or()ในงานแบช; การเปิดไฟล์หนึ่งครั้งและบันทึกหนึ่งครั้งดีกว่าการทำสี่ครั้ง - บันทึกจำนวนที่ได้รับผลกระทบต่อการผ่าน, รวมถึงศูนย์, เพื่อให้เห็นรูปแบบที่ไม่รู้จัก
การแก้ไขปัญหาที่พบบ่อย
The affected count is zero on a document you know is dirty
ตรวจสอบว่ารูปแบบอินพุตได้รับการรับรองก่อนสรุปว่าไฟล์สะอาด; ไฟล์ที่ไม่สามารถอ่านได้และไฟล์ที่สะอาดให้ผลลัพธ์เป็นศูนย์เดียวกัน
The leak check reports properties you just removed
ชี้การสแกนไปที่เส้นทางไฟล์ผลลัพธ์ที่บันทึกไว้, ไม่ใช่เส้นทางไฟล์อินพุต การสแกนจะอ่านไฟล์ที่ได้รับการระบุ
Comment balloons are still visible in Word
ข้อความคอมเมนต์อยู่ในเนื้อหาเอกสาร, ไม่ได้อยู่ในแพ็กเกจ metadata GroupDocs.Metadata จะลบคุณสมบัติที่เกี่ยวกับคอมเมนต์; การลบบอลลูนเองต้องใช้ไลบรารีแก้ไขเนื้อหาเช่น Aspose.Words
สรุป
สี่ขั้นตอน, หกฟังก์ชัน, สคริปต์เดียวที่รายงานสิ่งที่ทำ แท็กสเปคจัดการกลุ่มอัตลักษณ์ข้ามรูปแบบ, สเปคชื่อครอบคลุมกลุ่มที่แท็กไม่จัดประเภท, sanitize() จัดการขอบเขต, และการสแกนรั่วทำให้ทั้งหมดกลายเป็นการตรวจสอบ Clone รีโพซิทอรี, รันกับเอกสารที่ผ่านการตรวจทานจริง, แล้วดูจำนวนก่อนตัดสินใจว่าจะใช้การผ่านใดใน pipeline ของคุณ