Zum Inhalt springen
getnextpdf.com

Pro Edition

Vergleich

NextPDF\Pro\Diff vergleicht zwei PDF-Dokumente und meldet, was sich geändert hat. Der schnelle Pfad erzeugt einen seitenausgerichteten Text-Diff; der strukturierte Pfad ergänzt Bild- und Metadatenänderungserkennung und formatiert das Ergebnis als JSON oder HTML.

Diese Funktion wird in NextPDF Pro (nextpdf/pro) ausgeliefert und wird mit einer Lizenz-Envelope der Pro-Stufe aktiviert. Eine Bereitstellung ohne diese Berechtigung lädt die Klassen der Funktion nicht. Editionen vergleichen und Lizenz erwerben.

Kein Laufzeit-Fähigkeits-Flag schaltet die Diff-Klassen; sie sind vorhanden, sobald das Pro-Paket installiert ist.

Terminal-Fenster
composer require nextpdf/pro:^3

PdfDiffer::compare() extrahiert den Text je Seite aus jedem Dokument, teilt ihn in Zeilen auf und führt je Seitenpaar einen Myers-Zeilen-Diff aus, der hinzugefügte, entfernte und geänderte Regionen erzeugt. Die Textextraktion parst die textanzeigenden Operatoren von ISO 32000-2:2020 §9.4 (Tj, TJ, ').

StructuredDiffer baut darauf auf: Es gruppiert Textregionen zu Änderungen auf Absatzebene, vergleicht eingebettete Bilder, vergleicht Metadaten und erzeugt ein StructuredDiffResult mit einer aggregierten Zusammenfassung. DiffFormatter serialisiert dieses Ergebnis zu einem JSON-String oder einem HTML-Bericht-Fragment.

Wenn der optionale Artisan-PDF-Reader installiert ist, verwendet die Textextraktion ihn für seitengenauen Inhalt; andernfalls scannt eine begrenzte Rückfalloption auf Byteebene die Content-Streams direkt.

Der Differ vergleicht extrahierten Text und Struktur, nicht gerenderte Pixel. Ein struktureller Vergleich ist deterministisch, günstig und bildet die redaktionellen Änderungen ab, die einem Prüfer wichtig sind. Ein Pixel-Diff würde stattdessen Antialiasing- und Font-Hinting-Rauschen als Inhalt kennzeichnen. Da ein PDF Glyphen und Positionierung speichert und keine lesefertigen Zeichen, rekonstruiert jeder Vergleich zunächst den Text aus dem Content-Stream. Dieser Extraktionsschritt ist der Grund, warum der Artisan-Reader die Genauigkeit schärft, warum die begrenzte FlateDecode-Rückfalloption Abdeckung gegen Sicherheit eintauscht und warum gescannte Seiten kaum diffen. Die Seitenausrichtung bleibt zur Vorhersehbarkeit indexbasiert, sodass eine eingefügte Seite als deutliche nachgelagerte Verschiebung erscheint.

Design-Hintergrund: Warum der Text in einem PDF nicht wirklich Text ist.

  • Eingabe. Rohe PDF-Bytes für Quelle und Ziel. Ein Puffer, der nicht mit %PDF beginnt, löst InvalidArgumentException aus.
  • Ausgabe (schneller Pfad). DiffResult mit den Regionslisten added, removed, modified plus isIdentical(), hasDifferences(), totalChanges().
  • Ausgabe (strukturierter Pfad). StructuredDiffResult mit Absatz-Diffs, Bild-Diffs, Metadatenänderungen und einer DiffSummary.
  • Bericht-Ausgabe. DiffFormatter gibt einen JSON-String oder ein HTML-Fragment aus. Es erzeugt kein visuelles, nebeneinanderliegendes Redline-PDF.
  • Ressourcengrenzen. Die dekomprimierte Content-Stream-Größe ist begrenzt, um vor Dekomprimierungsbomben zu schützen; der Byteebenen-Scanner vermeidet katastrophales Regex-Backtracking bei manipulierter Eingabe.
  • Determinismus. Für identische Eingaben sind die Diff-Regionen und die formatierte Ausgabe stabil.
TypArtZentrale Mitglieder
NextPDF\Pro\Diff\PdfDifferfinal classstatic compare(string $sourcePdf, string $targetPdf): DiffResult, static compareTexts(array $sourcePages, array $targetPages): DiffResult, static extractText(string $contentStream): string
NextPDF\Pro\Diff\StructuredDifferfinal class__construct(?ImageDiffer $imageDiffer = null, ?MetadataDiffer $metadataDiffer = null), compare(string $sourcePdf, string $targetPdf): StructuredDiffResult
NextPDF\Pro\Diff\DiffFormatterfinal classtoJson(StructuredDiffResult $result): string, toHtml(StructuredDiffResult $result): string
NextPDF\Pro\Diff\DiffResultfinal readonly classarray $added, array $removed, array $modified, isIdentical(): bool, hasDifferences(): bool, totalChanges(): int
NextPDF\Pro\Diff\StructuredDiffResultfinal readonly classText-Diff, Absätze, Bilder, Metadatenänderungen, Zusammenfassung
NextPDF\Pro\Diff\DiffTypeenumAdded, Removed, Modified, Unchanged
<?php
declare(strict_types=1);
use NextPDF\Pro\Diff\PdfDiffer;
$diff = PdfDiffer::compare(
file_get_contents('v1.pdf'),
file_get_contents('v2.pdf'),
);
if ($diff->hasDifferences()) {
echo $diff->totalChanges(), " text changes detected\n";
}
<?php
declare(strict_types=1);
use NextPDF\Pro\Diff\DiffFormatter;
use NextPDF\Pro\Diff\StructuredDiffer;
function reviewReport(string $oldPdf, string $newPdf): string
{
$result = (new StructuredDiffer())->compare($oldPdf, $newPdf);
// JSON for machine consumption; toHtml() for a review UI fragment.
return (new DiffFormatter())->toJson($result);
}
  • Der Diff ist nach Index seitenausgerichtet. Das Einfügen einer Seite weiter vorne verschiebt alle späteren Seiten und meldet große nachgelagerte Änderungen — das ist für einen indexausgerichteten Vergleich zu erwarten.
  • Der Bildvergleich erkennt hinzugefügte, entfernte und geänderte eingebettete Bilder; er ist kein perzeptueller visueller Diff und rendert keine Seiten pixelweise.
  • Gescannte reine Bild-PDFs erzeugen wenig oder keinen Text-Diff, weil kein OCR durchgeführt wird.
  • Ohne den optionalen Artisan-Reader verwendet die Extraktion die begrenzte Rückfalloption; stark komprimierte Dokumente können eine verringerte Textabdeckung liefern.

Die Textextraktion ist linear in den Dokumentbytes; der Myers-Diff ist nahezu linear für ähnliche Dokumente und im schlimmsten Fall quadratisch je Seitenpaar. Die Dekomprimierungsgrenze begrenzt den Speicher. Siehe performance_budget.

Die Byteebenen-Rückfalloption verwendet strpos-basiertes Scannen statt unbegrenzter Regex, um katastrophales Backtracking bei manipulierten PDFs zu vermeiden, und begrenzt die Dekomprimierungsausgabe. Das Diffing führt keine eingebetteten Skripte aus. Siehe das Core-Sicherheitsmodell.

AussageSpec-KlauselStatus
Tj-Textoperator zur Extraktion geparstISO 32000-2:2020 §9.4Verifiziert (Unit-Suite)
TJ-Array-Textoperator zur Extraktion geparstISO 32000-2:2020 §9.4Verifiziert (Unit-Suite)
Visuelle nebeneinanderliegende Redline-PDF-AusgabeNicht unterstützt (nur JSON/HTML)

Für den Dokumentvergleich existiert kein Core-Äquivalent. Der optionale Artisan-Reader verbessert die Extraktionsgenauigkeit, wenn er installiert ist, ist aber nicht erforderlich.

Dies ist ein Inhaltsänderungs-Detektor. Er ist kein forensischer Differenzanalysator und erzeugt keine beweis- oder manipulationszuordnenden Berichte; diese Anliegen liegen außerhalb des Geltungsbereichs dieses Moduls.

Diese Seite dokumentiert ausschließlich extern beobachtbares Verhalten und die unterstützte öffentliche API-Oberfläche. Interne Namespace-Pfade, Hilfsklassen, Mechanismustabellen, Runbook-Dateinamen und Ticket-Präfixe liegen außerhalb des Geltungsbereichs.