💡 Voll funktionsfähiges Beispiel auf GitHub verfügbar:
metadata-diff-doc-versions-using-groupdocs-metadata-nodejs

Einführung

Der Metadatenvergleich ist eine Fähigkeit von GroupDocs.Metadata, die versteckte Änderungen zwischen Dokumentversionen aufdeckt und Auditoren ermöglicht, die Authentizität schnell zu überprüfen. Wenn Rechtsteams nachweisen müssen, dass ein Vertrag nicht manipuliert wurde, erzählen die unsichtbaren Eigenschaften – Autor, Bearbeiter, Zeitstempel von Revisionen – oft die wahre Geschichte.

Ich stieß auf dieses Problem, als ich einen Stapel Lieferantenverträge prüfte; jede Datei gab dasselbe Erstellungsdatum an, aber die versteckten Autorenfelder unterschieden sich, und die manuelle Prüfung hätte Stunden gedauert.

Warum versteckte Metadaten für Rechtsteams wichtig sind

Rechts- und Compliance‑Fachleute verlassen sich auf unveränderliche Beweise. Selbst wenn der sichtbare Text gleich bleibt, kann eine Änderung im Creator‑ oder LastPrinted‑Feld unautorisierte Änderungen anzeigen. Das frühzeitige Erkennen dieser Verschiebungen verhindert kostspielige Streitigkeiten und erfüllt regulatorische Prüfpfade.

Unsere Lösung mit GroupDocs.Metadata

GroupDocs.Metadata für Node.js bietet eine einheitliche API, die jede unterstützte Eigenschaft extrahiert, zwei Revisionen vergleicht und strukturierte Diff‑Berichte erzeugt. Das SDK unterstützt DOCX, PDF, XLSX und viele weitere Formate out‑of‑the‑box, sodass keine eigenen Parser für jeden Dateityp nötig sind.

Schritt 1 – Alle Metadaten aus einem Dokument extrahieren

Der untenstehende Helfer öffnet eine Datei, durchläuft den gesamten Eigenschaftsbaum und gibt eine einfache JavaScript‑Map von Eigenschaftsname → Wert zurück. Er verwendet die AnySpecification, um sowohl integrierte als auch benutzerdefinierte Felder zu erfassen.

/** 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;
}

Leistungshinweis: Das Extrahieren von Metadaten aus einer 5 MB DOCX dauert weniger als 200 ms auf einer typischen 2 GHz CPU [Docs][DOCS_URL].

Schritt 2 – Unterschiede zwischen zwei Revisionen erkennen

Mit beiden Versionen als einfachen Objekten erstellt die Diff‑Routine drei Buckets – added, removed und changed – und stellt einen praktischen totalChanges‑Getter bereit.

/** 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;
    },
  };
}

Schritt 3 – Eigentums‑ und Revisions‑Einblicke (optional)

Erkennen von Eigentumsänderungen

Rechtsprüfer konzentrieren sich häufig darauf, wer ein Dokument erstellt oder bearbeitet hat. Dieser Helfer isoliert diese Felder und markiert jede Abweichung.

/** 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;
}

Erkennen von Änderungen in der Revisionshistorie

Revisionsnummer, gesamte Bearbeitungszeit und Zeitstempel des letzten Drucks enthüllen versteckte Aktivitäten.

/** 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;
}

Schritt 4 – Audit‑Berichte exportieren

CSV‑Export

Das CSV‑Format ist ideal für Excel oder SIEM‑Einspeisung. Felder werden escaped, um Kommata und Zeilenumbrüche zu handhaben.

/** 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 bewahrt die hierarchische Struktur für die programmgesteuerte Nutzung.

/** 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');
}

Vollständiges Treiberskript

Das Skript verbindet alles, gibt