Pro Edition
Writer — Ausführliche Referenz
Auf einen Blick
Abschnitt betitelt „Auf einen Blick“Das Writer-Modul schreibt PDF-Revisionen als inkrementelle Aktualisierungen und packt kleine Objekte in Object Streams. Der inkrementelle Writer erzwingt eine fail-closed Append-only-Regel: Jedes Byte, das der Puffer vor einer Revision enthielt, muss danach unverändert bleiben. Der Object-Stream-Builder gruppiert geeignete Objekte in ein einzelnes FlateDecode-komprimiertes /Type /ObjStm-Objekt innerhalb einer festgelegten Größe.
Verfügbarkeit & Lizenzierung
Abschnitt betitelt „Verfügbarkeit & Lizenzierung“Diese Fähigkeit wird mit NextPDF Pro (nextpdf/pro) ausgeliefert und wird mit einem Lizenz-Envelope der Pro-Stufe aktiviert. Eine Bereitstellung ohne diese Berechtigung lädt die Klassen der Fähigkeit nicht. Editionen vergleichen und eine Lizenz erwerben. Es gibt kein Lizenz-Flag pro Feature; der Code wird mit der Pro-Edition ausgeliefert.
Öffentliche API-Oberfläche
Abschnitt betitelt „Öffentliche API-Oberfläche“Das Modul liegt im Namespace NextPDF\Pro\Writer. Alle öffentlichen Symbole sind unten aufgeführt. Value Objects sind unveränderliche final readonly-Klassen.
| Symbol | Parameter | Standardverhalten | Rückgabe | Wirft oder scheitert mit | Hinweise |
|---|---|---|---|---|---|
IncrementalUpdateWriter::writeRevision | BinaryBuffer $buffer, ObjectRegistry $registry, int $prevXrefOffset, int $catalogObject, array $catalogEntries, array $catalogUpdates, array $newObjectNumbers, string $fileId | Statisch. Schreibt den Katalog mit zusammengeführten Einträgen neu, hängt eine traditionelle Cross-Reference-Tabelle für neue und geänderte Objekte an und schreibt einen Trailer mit /Size, /Root, /Prev und /ID. Prüft danach, ob das Präfix vor der Revision byteweise gleich ist. | int — Byte-Offset der neuen Cross-Reference-Tabelle | \NextPDF\Exception\WriterException, wenn die Append-only-Präfixprüfung fehlschlägt; getWriterState() gibt dss-append-only-invariant zurück | Statischer Einstiegspunkt. Bei einer Verletzung keine verwertbare Ausgabe. |
ObjectStreamWriter::addObject | int $objectNumber, string $content | Hängt nach einer Größenprüfung ein Objekt an den ausstehenden Stream an. | void | OverflowException, wenn der kombinierte Index plus Body 65.536 Bytes überschreiten würde | $content schließt die N 0 obj / endobj-Wrapper aus. |
ObjectStreamWriter::canAccept | string $content | Schätzt den Index-Overhead und prüft die laufende Summe gegen das Maximum. | bool | Wirft nicht | Reines Prädikat; keine Zustandsänderung. |
ObjectStreamWriter::build | keine | Baut den Index auf, verkettet die Bodies, komprimiert mit FlateDecode und umschließt das /Type /ObjStm-Dictionary. | string — Roher Object-Stream-Inhalt | ObjectStreamWriteException, wenn keine Objekte hinzugefügt wurden, oder bei einem zlib-Komprimierungsfehler | Der Aufrufer weist die Objektnummer zu und umschließt die Marker. |
ObjectStreamWriter::getEntries | keine | Berechnet die body-relativen Offsets für die akkumulierten Objekte neu. | list<ObjectStreamEntry> | Wirft nicht | Offsets sind relativ zum Body-Abschnitt. |
ObjectStreamWriter::count | keine | Meldet die Anzahl der akkumulierten Objekte. | int | Wirft nicht | — |
ObjStmCompressor::__construct | int $maxStreamSize = 65536, int $maxObjectsPerStream = 200 | Speichert die für die Gruppierung verwendeten Größen- und Objektanzahl-Grenzen. | — | Wirft nicht | Die Standardwerte entsprechen dem Object-Stream-Tuning des Moduls. |
ObjStmCompressor::groupObjects | list<array{number: int, generation?: int, content: string}> $objects | Filtert ungeeignete Objekte heraus und packt dann den Rest innerhalb der Größen- und Anzahlgrenzen in Writer. | list<ObjectStreamWriter> | Wirft nicht; ungeeignete Objekte werden übersprungen | Objekte mit einer Generation ungleich null fallen auf die normale Serialisierung zurück. |
ObjStmCompressor::isEligible | string $content, int $generation = 0 | Weist Stream-Objekte, /Encrypt, /XRef, /Catalog und jede Generation ungleich null zurück. | bool | Wirft nicht | Das /Type-Matching ist tolerant gegenüber Whitespace und #xx-Escapes. |
ObjStmCompressor::writeToBuffer | list<ObjectStreamWriter> $streams, BinaryBuffer $buffer, ObjectRegistry $registry | Allokiert ein Trägerobjekt pro Stream, registriert Typ-2-komprimierte Einträge und schreibt jeden ObjStm-Block. | list<int> — Objektnummern der Trägerobjekte | Propagiert ObjectStreamWriteException aus build() bei einem seltenen Komprimierungsfehler | Nach dem Schreiben der nicht geeigneten Objekte und vor der Ausgabe der Cross-Reference auszuführen. |
ObjStmCompressor::estimateSavings | list<ObjectStreamWriter> $streams, int $originalSize | Baut jeden Stream auf, um die komprimierte Größe gegen das Original zu messen. | ObjStmCompressionResult | Propagiert ObjectStreamWriteException aus build() bei einem seltenen Komprimierungsfehler | Schreibgeschützter Mess-Helfer. |
ObjectStreamEntry::__construct | int $objectNumber, string $content, int $offset | Unveränderlicher Datensatz eines gepackten Objekts und seines Body-Offsets. | — | Wirft nicht | final readonly; öffentliche Properties. |
ObjStmCompressionResult::__construct | int $originalObjectCount, int $streamCount, int $estimatedOriginalSize, int $estimatedCompressedSize | Unveränderlicher Metrik-Container. | — | Wirft nicht | final readonly; öffentliche Properties. |
ObjStmCompressionResult::savedBytes | keine | Gibt die Originalgröße minus die komprimierte Größe zurück. | int | Wirft nicht | Kann negativ sein, wenn das Packen die Daten vergrößert hat. |
ObjStmCompressionResult::savedPercent | keine | Gibt die prozentuale Reduktion zurück. | float | Wirft nicht | Gibt 0.0 zurück, wenn die Originalgröße null ist. |
ObjStmCompressionResult::compressionRatio | keine | Gibt die komprimierte Größe geteilt durch das Original zurück. | float | Wirft nicht | Gibt 1.0 zurück, wenn die Originalgröße null ist. |
ObjectStreamWriteException | — | Signalisiert einen Fehler beim Aufbau eines Object Streams. | — | Erweitert RuntimeException | Von build() geworfen; über RuntimeException abfangbar zur Abwärtskompatibilität. |
Signaturen der Einstiegspunkte
Abschnitt betitelt „Signaturen der Einstiegspunkte“final class IncrementalUpdateWriter{ public static function writeRevision( BinaryBuffer $buffer, ObjectRegistry $registry, int $prevXrefOffset, int $catalogObject, array $catalogEntries, array $catalogUpdates, array $newObjectNumbers, string $fileId, ): int;}final class ObjectStreamWriter{ public function addObject(int $objectNumber, string $content): void; public function canAccept(string $content): bool; public function build(): string; /** @return list<ObjectStreamEntry> */ public function getEntries(): array; public function count(): int;}final class ObjStmCompressor{ public function __construct( int $maxStreamSize = 65536, int $maxObjectsPerStream = 200, );
/** * @param list<array{number: int, generation?: int, content: string}> $objects * @return list<ObjectStreamWriter> */ public function groupObjects(array $objects): array;
public function isEligible(string $content, int $generation = 0): bool;
/** * @param list<ObjectStreamWriter> $streams * @return list<int> */ public function writeToBuffer(array $streams, BinaryBuffer $buffer, ObjectRegistry $registry): array;
/** @param list<ObjectStreamWriter> $streams */ public function estimateSavings(array $streams, int $originalSize): ObjStmCompressionResult;}Verhaltensvertrag
Abschnitt betitelt „Verhaltensvertrag“writeRevision schreibt eine Revision als inkrementelle Aktualisierung. Es erstellt vor dem Schreiben einen Snapshot des bestehenden Puffer-Präfixes. Es schreibt den Katalog mit zusammengeführten Einträgen neu, registriert neue Objekt-Offsets, schreibt eine traditionelle Cross-Reference-Tabelle, die in zusammenhängende Untersektionen gruppiert ist, und schreibt einen Trailer mit /Size, /Root, /Prev und /ID. Nach dem Schreiben vergleicht es das Präfix erneut. Wenn sich ein früheres Byte geändert hat, wirft es WriterException mit dem Zustand der Append-only-Verletzung und gibt keine verwertbare Ausgabe zurück. Bei Erfolg gibt es den Byte-Offset der neuen Cross-Reference-Tabelle zur Verkettung weiterer Revisionen zurück. Das Mischen von Cross-Reference-Tabellen und -Streams über Revisionen hinweg ist erlaubt.
ObjectStreamWriter akkumuliert Objekte. addObject wirft einen Overflow-Fehler, wenn der kombinierte Index und Body das Maximum von 65.536 Bytes unkomprimiert überschreiten würden. build wirft einen Fehler bei einem leeren Stream; andernfalls komprimiert es den Index plus Body und gibt den Object-Stream-Inhalt mit den Einträgen /Type /ObjStm, /N, /First, /Length und /Filter /FlateDecode zurück. Der Aufrufer weist die Objektnummer zu und umschließt die N 0 obj / endobj-Marker.
ObjStmCompressor entscheidet, welche Objekte gepackt werden. Es schließt Stream-Objekte, Verschlüsselungs-Dictionaries, Cross-Reference-Streams, den Dokumentkatalog und jedes Objekt mit einer Generationsnummer ungleich null aus. writeToBuffer allokiert ein Trägerobjekt pro Stream, registriert jedes gepackte Objekt als Typ-2-komprimierten Cross-Reference-Eintrag und schreibt den ObjStm-Block am aktuellen Puffer-Offset. estimateSavings baut jeden Stream auf, um Größenmetriken zu berechnen, ohne den Puffer zu verändern.
Grenzfälle & Fehlermodi
Abschnitt betitelt „Grenzfälle & Fehlermodi“- Die Append-only-Prüfung kopiert das bestehende Präfix. Ihre Kosten wachsen mit der Größe des bereits geschriebenen Dokuments. Diese Kosten sind beabsichtigt und schützen signierte Bytes.
- Die Object-Stream-Grenze gilt für den unkomprimierten Index plus Body. Platzieren Sie das Verschlüsselungs-Dictionary und andere ausgeschlossene Objekttypen als direkte indirekte Objekte.
- Der
/Type-Ausschluss ist tolerant gegenüber beliebigem Whitespace zwischen Tokens und#xx-Hex-Escapes. Formen wie/Type /Encrypt,/Type\n/Encryptund/Type /#45ncryptwerden allesamt zurückgewiesen, nicht nur die kanonische literale Schreibweise. - Jedes Objekt mit einer Generationsnummer ungleich null wird als ungeeignet behandelt und fällt auf die normale
N G obj … endobj-Serialisierung zurück, da die Generation eines komprimierten Objekts implizit null ist. writeToBuffermuss ausgeführt werden, nachdem alle nicht geeigneten Objekte geschrieben wurden und bevor die Cross-Reference ausgegeben wird. Gepackte Objekte dürfen nicht zusätzlich separat serialisiert werden.
Verhalten im FIPS-Modus
Abschnitt betitelt „Verhalten im FIPS-Modus“Das Writer-Modul führt keine kryptografischen Operationen durch. Es schützt signierte Bytes, indem es die Ausgabe verweigert, wenn sich ein früheres Byte ändern würde, was eine Byte-Gleichheitsprüfung und keine kryptografische Prüfung ist. Die FIPS-Algorithmusauswahl für Signierung und Hashing wird vom Signaturmodul gesteuert, nicht von diesem Writer. Das Aktivieren oder Deaktivieren des FIPS-Modus ändert das Verhalten keiner Writer-Methode.
Konformität
Abschnitt betitelt „Konformität“NextPDF implementiert das Modul gegen ISO 32000-2:2020. Der inkrementelle Writer folgt der Grammatik für inkrementelle Aktualisierungen aus §7.5.6: Jede Revision hängt eine Cross-Reference-Sektion an, die nur neue, geänderte oder gelöschte Objekte abdeckt, sowie einen Trailer, dessen /Prev-Eintrag den Offset der vorherigen Cross-Reference angibt. Der Object-Stream-Builder folgt dem Object-Stream-Modell aus §7.5.7: Ein Index aus Paaren von Objektnummer und Offset, mit ab dem /First-Eintrag in aufsteigender Reihenfolge gemessenen Offsets, geht den gepackten Objekt-Bodies voraus. Beide Klauselreferenzen wurden gegen das Korpus von ISO 32000-2:2020 verifiziert. Die Revisionsverkettung für PAdES B-LT- und B-LTA-Workflows folgt ETSI EN 319 142-1 §5.4, wie im Quellcode annotiert. Die Unterstützung einer Klausel ist eine technische Fähigkeitsaussage, keine Zertifizierung; NextPDF besitzt keine formale Konformitätszertifizierung.
Entwicklungshinweise
Abschnitt betitelt „Entwicklungshinweise“- Installieren Sie das Paket mit
composer require nextpdf/pro:^3. Die Klassen werden unterNextPDF\Pro\Writeraufgelöst. IncrementalUpdateWriter::writeRevisionist ein statischer Einstiegspunkt; es hält keinen Instanzzustand zwischen Revisionen.ObjectStreamEntry,ObjStmCompressionResult,IncrementalUpdateWriterund der Compressor bilden zusammen die öffentliche Oberfläche des Moduls; das Repository liefert kein lauffähiges Beispiel dafür aus.- Eine
WriterExceptionauswriteRevisionweist auf eine Append-only-Verletzung hin. Behandeln Sie sie als harten Fehler und verwerfen Sie den Puffer. - Object-Stream-Träger sind indirekte Objekte; der Aufrufer weist ihre Objektnummern über die Registry zu.
Publikationsgrenze
Abschnitt betitelt „Publikationsgrenze“Diese Seite dokumentiert ausschließlich das extern beobachtbare Verhalten und die unterstützte öffentliche API-Oberfläche. Interne Namespace-Pfade, Hilfsklassen, Mechanismus-Tabellen, Runbook-Dateinamen und Ticket-Präfixe sind nicht im Umfang enthalten.