💡 Volledig werkend voorbeeld beschikbaar op GitHub:
metadata-diff-doc-versions-using-groupdocs-metadata-nodejs
Introduction
Metadata‑vergelijking is een functionaliteit van GroupDocs.Metadata die verborgen wijzigingen tussen documentversies onthult, waardoor auditors snel de authenticiteit kunnen verifiëren. Wanneer juridische teams moeten aantonen dat een contract niet is gemanipuleerd, vertellen de onzichtbare eigenschappen — auteur, editor, revisietijdstempels — vaak het echte verhaal.
Ik kwam dit probleem tegen tijdens het beoordelen van een reeks leverancierscontracten; elk bestand gaf dezelfde aanmaakdatum weer, maar de verborgen auteur‑velden verschilden, en de handmatige audit zou uren hebben gekost.
Why hidden metadata matters for legal teams
Juridische en compliance‑professionals vertrouwen op onveranderlijk bewijs. Zelfs als de zichtbare tekst gelijk blijft, kan een wijziging in het Creator‑ of LastPrinted‑veld duiden op ongeautoriseerde bewerkingen. Het vroegtijdig detecteren van deze verschuivingen voorkomt kostbare geschillen en voldoet aan de vereiste audit‑trails.
Our solution with GroupDocs.Metadata
GroupDocs.Metadata voor Node.js biedt een enkele API die elke ondersteunde eigenschap extraheert, twee revisies vergelijkt en gestructureerde diff‑rapporten genereert. De SDK ondersteunt DOCX, PDF, XLSX en vele andere formaten out‑of‑the‑box, zodat je geen aangepaste parsers voor elk bestandstype nodig hebt.
Step 1 – Pulling all metadata from a document
De helper hieronder opent een bestand, doorloopt de volledige eigenschapsboom en retourneert een eenvoudige JavaScript‑map van eigenschapnaam → waarde. Hij gebruikt de AnySpecification om zowel ingebouwde als aangepaste velden vast te leggen.
/** 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: het extraheren van metadata uit een DOCX van 5 MB duurt minder dan 200 ms op een typische 2 GHz CPU Docs.
Step 2 – Spotting differences between two revisions
Met beide versies weergegeven als eenvoudige objecten bouwt de diff‑routine drie verzamelingen — added, removed en changed — en biedt een handige totalChanges‑getter.
/** 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;
},
};
}
Step 3 – Ownership and revision insights (optional)
Detecting ownership changes
Juridische auditors richten zich vaak op wie een document heeft aangemaakt of bewerkt. Deze helper isoleert die velden en markeert elke afwijking.
/** 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;
}
Detecting revision‑history changes
Revisienummer, totale bewerkingstijd en timestamps van de laatste afdruk onthullen verborgen activiteit.
/** 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;
}
Step 4 – Exporting audit reports
CSV export
Het CSV‑formaat is ideaal voor Excel of SIEM‑invoer. Velden worden geescaped om komma’s en regeleinden te verwerken.
/** 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 export
JSON behoudt de hiërarchische structuur voor programmatische consumptie.
/** 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');
}
Full driver script
Het script koppelt alles samen, geeft een korte samenvatting weer en schrijft zowel CSV‑ als JSON‑rapporten weg.
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'));
Het uitvoeren van node index.js maakt metadata-diff.csv en metadata-diff.json aan in de project‑root.
How can I compare metadata between two versions of a document?
Je vergelijkt metadata door elke revisie te laden met de Metadata‑klasse, een platte naam‑naar‑waarde‑map te extraheren via extractAllMetadata, en de twee mappen door te geven aan compareMetadataSets. De functie retourneert drie collecties — added, removed en changed — plus een totalChanges‑teller. Dit werkt voor elk formaat dat door GroupDocs.Metadata wordt ondersteund (DOCX, PDF, XLSX, PPTX, enz.) en voltooit ruim onder een seconde voor typische kantoordocumenten, waardoor het geschikt is voor batchverwerking of CI‑integratie.
Business impact
| Metric | Manual process | Automated with GroupDocs.Metadata |
|---|---|---|
| Tijd per document | ~45 min (handmatige beoordeling) | <30 s (metadata‑diff) |
| Foutpercentage | ~3 % gemiste wijzigingen | 0 % – elke eigenschap wordt onderzocht |
| Doorvoersnelheid | 20 docs/dag per reviewer | 1 000 + docs/dag op een bescheiden VM |
| Audit‑trail | Handgeschreven notities | Gestructureerde CSV/JSON‑logboeken |
| Kosten | $X / uur × N reviewers | Vaste licentie, onbeperkt gebruik |
De automatisering verkort de beoordelingsduur met meer dan 99 %, elimineert menselijke fouten en levert een machine‑leesbare audit‑trail die direct kan worden geïntegreerd in compliance‑dashboards.
Getting started in your environment
- Probeer het gratis – vraag hier een tijdelijke 30‑daagse licentie aan here.
- Installeer de SDK –
npm install @groupdocs/groupdocs.metadata. - Voer het voorbeeld uit – kloon de GitHub‑repo en voer
node index.jsuit. - Verken meer – bekijk de volledige API‑referentie voor geavanceerde filters en aangepaste eigenschapsafhandeling.