💡 完整的工作範例可在 GitHub 上取得: metadata-diff-doc-versions-using-groupdocs-metadata-nodejs
介紹
Metadata comparison 是 GroupDocs.Metadata 的功能,能揭示文件版本之間的隱藏變更,讓稽核人員快速驗證真偽。當法律團隊需要證明合約未被竄改時,隱藏的屬性——作者、編輯者、修訂時間戳——往往說明了真相。
我在審查一批供應商協議時遇到這個問題;每個檔案都聲稱相同的建立日期,但隱藏的作者欄位卻不同,若手動稽核將耗費數小時。
為何隱藏的中繼資料對法律團隊很重要
法律與合規專業人員依賴不可變的證據。即使可見文字保持不變,Creator 或 LastPrinted 欄位的變更也可能表示未授權的編輯。及早偵測這些變化可防止昂貴的爭議,並滿足法規稽核追蹤的需求。
我們使用 GroupDocs.Metadata 的解決方案
GroupDocs.Metadata for Node.js 提供單一 API,能提取所有支援的屬性、比較兩個修訂,並產生結構化的差異報告。SDK 內建支援 DOCX、PDF、XLSX 等多種格式,無需為每種檔案類型自行撰寫解析器。
步驟 1 – 從文件中提取所有中繼資料
以下輔助程式會開啟檔案、遍歷完整屬性樹,並回傳 屬性名稱 → 值 的純 JavaScript 映射。它使用 AnySpecification 來捕獲內建與自訂欄位。
/** Extract all metadata from a file */
function extractAllMetadata(documentPath) {
const result = {};
const metadata = new groupdocs.Metadata(documentPath);
try {
const properties = metadata.findProperties(new groupdocs.AnySpecification());
for (let i = 0; i < properties.getCount(); i++) {
const p = properties.get_Item(i);
const name = p.getName();
const value = valueToString(p);
result[name] = value;
}
} finally {
metadata.close();
}
return result;
}
Performance note: extracting metadata from a 5 MB DOCX completes in under 200 ms on a typical 2 GHz CPU Docs。
步驟 2 – 發現兩個版本之間的差異
將兩個版本皆以純物件表示後,diff 程式會建立三個集合——added、removed、changed——並提供便利的 totalChanges 取得器。
/** Compare two metadata maps */
function compareMetadataSets(pathV1, pathV2) {
const v1 = extractAllMetadata(pathV1);
const v2 = extractAllMetadata(pathV2);
const added = {};
const removed = {};
const changed = {};
for (const k of Object.keys(v2)) {
if (!(k in v1)) added[k] = v2[k];
else if (v1[k] !== v2[k]) changed[k] = { from: v1[k], to: v2[k] };
}
for (const k of Object.keys(v1)) {
if (!(k in v2)) removed[k] = v1[k];
}
return {
added,
removed,
changed,
get totalChanges() {
return Object.keys(this.added).length + Object.keys(this.removed).length + Object.keys(this.changed).length;
},
};
}
步驟 3 – 所有權與版本洞察(可選)
偵測所有權變更
法律稽核人員常關注誰建立或編輯了文件。此輔助程式會挑出相關欄位,並標記任何差異。
/** Ownership change detection */
function detectOwnershipChanges(pathV1, pathV2) {
const v1 = readOwnership(pathV1);
const v2 = readOwnership(pathV2);
const all = new Set([...Object.keys(v1), ...Object.keys(v2)]);
const changes = {};
for (const k of all) {
const oldV = v1[k] !== undefined ? v1[k] : '<missing>';
const newV = v2[k] !== undefined ? v2[k] : '<missing>';
if (oldV !== newV) changes[k] = { from: oldV, to: newV };
}
return changes;
}
偵測版本歷史變更
修訂號、總編輯時間與最後列印時間戳可揭露隱藏的活動。
/** Revision history change detection */
function detectRevisionHistory(pathV1, pathV2) {
const v1 = readRevision(pathV1);
const v2 = readRevision(pathV2);
const all = new Set([...Object.keys(v1), ...Object.keys(v2)]);
const changes = {};
for (const k of all) {
const oldV = v1[k] !== undefined ? v1[k] : '<missing>';
const newV = v2[k] !== undefined ? v2[k] : '<missing>';
if (oldV !== newV) changes[k] = { from: oldV, to: newV };
}
return changes;
}
步驟 4 – 匯出稽核報告
CSV 匯出
CSV 格式適合 Excel 或 SIEM 匯入。欄位會進行跳脫,以處理逗號與換行。
/** Export diff to CSV */
function exportDiffToCsv(diff, outputPath) {
const rows = ['change_type,property,old_value,new_value'];
for (const [k, v] of Object.entries(diff.added)) rows.push(`added,${esc(k)},,${esc(v)}`);
for (const [k, v] of Object.entries(diff.removed)) rows.push(`removed,${esc(k)},${esc(v)},`);
for (const [k, o] of Object.entries(diff.changed)) rows.push(`changed,${esc(k)},${esc(o.from)},${esc(o.to)}`);
fs.writeFileSync(outputPath, rows.join('\n') + '\n', 'utf-8');
}
JSON 匯出
JSON 能保留階層結構,方便程式化使用。
/** Export diff to JSON */
function exportDiffToJson(diff, outputPath) {
const payload = { added: diff.added, removed: diff.removed, changed: diff.changed };
fs.writeFileSync(outputPath, JSON.stringify(payload, null, 2), 'utf-8');
}
完整驅動腳本
此腳本將所有功能串接起來,快速列印摘要,並同時寫入 CSV 與 JSON 報告。
const path = require('path');
const fs = require('fs');
const groupdocs = require('@groupdocs/groupdocs.metadata');
function esc(txt) { return /[",\n]/.test(txt) ? `"${txt.replace(/"/g, '""')}"` : txt; }
const diff = compareMetadataSets('resources/document-v1.docx', 'resources/document-v2.docx');
console.log(`Total metadata changes: ${diff.totalChanges}`);
exportDiffToCsv(diff, path.resolve('metadata-diff.csv'));
exportDiffToJson(diff, path.resolve('metadata-diff.json'));
執行 node index.js 後,會在專案根目錄產生 metadata-diff.csv 與 metadata-diff.json。
如何比較文件兩個版本之間的中繼資料?
您可以透過 Metadata 類別載入每個修訂,使用 extractAllMetadata 取得平面「名稱 → 值」映射,然後將兩個映射傳入 compareMetadataSets。此函式會回傳三個集合——added、removed、changed——以及 totalChanges 計數。此方式適用於 GroupDocs.Metadata 支援的任何格式(DOCX、PDF、XLSX、PPTX 等),且在一般辦公文件上執行時間遠低於一秒,適合批次處理或 CI 整合。
商業影響
| 指標 | 手動流程 | 使用 GroupDocs.Metadata 自動化 |
|---|---|---|
| 每份文件所需時間 | ~45 min (手動審查) | <30 s (metadata diff) |
| 錯誤率 | ~3 % 漏掉變更 | 0 % – 每個屬性皆被檢查 |
| 吞吐量 | 20 份/天/審核員 | 1 000 + 份/天於一般 VM |
| 稽核追蹤 | 手寫筆記 | 結構化 CSV/JSON 日誌 |
| 成本 | $X / 小時 × N 位審核員 | 固定授權,無限制執行次數 |
自動化將審查時間縮短超過 99 %,消除人工錯誤,並提供可直接匯入合規儀表板的機器可讀稽核追蹤。
在您的環境中開始使用
- 免費試用 – 於此取得 30 天臨時授權 here。
- 安裝 SDK –
npm install @groupdocs/groupdocs.metadata。 - 執行範例 – 下載 GitHub 專案並執行
node index.js。 - 深入探索 – 參閱完整 API 參考,了解進階篩選與自訂屬性處理。