Aller au contenu
getnextpdf.com

Pro édition

Writer — Référence détaillée

Le module Writer écrit des révisions PDF par mise à jour incrémentale et regroupe les petits objets dans des Object Streams. Le writer incrémental applique une règle d’ajout seul en fail-closed : chaque octet que le tampon contenait avant une révision doit rester inchangé après celle-ci. Le constructeur d’Object Stream regroupe les objets éligibles dans un seul objet /Type /ObjStm compressé en FlateDecode, sous une taille bornée.

Cette capacité est fournie dans NextPDF Pro (nextpdf/pro) et s’active avec une enveloppe de licence de niveau Pro. Un déploiement sans ce droit ne charge pas les classes de la capacité. Compare les éditions et obtiens une licence. Il n’existe pas d’indicateur de licence par fonctionnalité ; le code est livré avec l’édition Pro.

Le module réside dans l’espace de noms NextPDF\Pro\Writer. Tous les symboles publics sont listés ci-dessous. Les objets valeur sont des classes final readonly immuables.

SymboleParamètresComportement par défautRenvoieLève ou échoue avecNotes
IncrementalUpdateWriter::writeRevisionBinaryBuffer $buffer, ObjectRegistry $registry, int $prevXrefOffset, int $catalogObject, array $catalogEntries, array $catalogUpdates, array $newObjectNumbers, string $fileIdStatique. Réécrit le catalogue avec les entrées fusionnées, ajoute une table de références croisées traditionnelle pour les objets nouveaux et modifiés, et écrit un trailer avec /Size, /Root, /Prev et /ID. Vérifie ensuite que le préfixe d’avant la révision est identique octet pour octet.int — décalage en octets de la nouvelle table de références croisées\NextPDF\Exception\WriterException lorsque la vérification du préfixe en ajout seul échoue ; getWriterState() renvoie dss-append-only-invariantPoint d’entrée statique. Aucune sortie exploitable en cas de violation.
ObjectStreamWriter::addObjectint $objectNumber, string $contentAjoute un objet au flux en attente après une vérification de taille.voidOverflowException lorsque l’index combiné plus le corps dépasseraient 65,536 octets$content exclut les encadrants N 0 obj / endobj.
ObjectStreamWriter::canAcceptstring $contentEstime le surcoût d’index et teste le total courant par rapport au maximum.boolNe lève pas d’exceptionPrédicat pur ; aucun changement d’état.
ObjectStreamWriter::buildaucunConstruit l’index, concatène les corps, compresse avec FlateDecode et encapsule le dictionnaire /Type /ObjStm.string — contenu brut de l’Object StreamObjectStreamWriteException lorsqu’aucun objet n’a été ajouté, ou en cas d’échec de compression zlibL’appelant attribue le numéro d’objet et ajoute les marqueurs.
ObjectStreamWriter::getEntriesaucunRecalcule les décalages relatifs au corps pour les objets accumulés.list<ObjectStreamEntry>Ne lève pas d’exceptionLes décalages sont relatifs à la section du corps.
ObjectStreamWriter::countaucunIndique le nombre d’objets accumulés.intNe lève pas d’exception
ObjStmCompressor::__constructint $maxStreamSize = 65536, int $maxObjectsPerStream = 200Stocke les limites de taille et de nombre d’objets utilisées pour le regroupement.Ne lève pas d’exceptionLes valeurs par défaut correspondent au réglage Object Stream du module.
ObjStmCompressor::groupObjectslist<array{number: int, generation?: int, content: string}> $objectsFiltre les objets non éligibles, puis regroupe le reste dans des writers en respectant les limites de taille et de nombre.list<ObjectStreamWriter>Ne lève pas d’exception ; les objets non éligibles sont ignorésLes objets de génération non nulle passent à la sérialisation normale.
ObjStmCompressor::isEligiblestring $content, int $generation = 0Rejette les objets flux, /Encrypt, /XRef, /Catalog et toute génération non nulle.boolNe lève pas d’exceptionLa correspondance /Type tolère les espaces et les échappements #xx.
ObjStmCompressor::writeToBufferlist<ObjectStreamWriter> $streams, BinaryBuffer $buffer, ObjectRegistry $registryAlloue un objet porteur par flux, enregistre les entrées compressées de type 2 et écrit chaque bloc ObjStm.list<int> — numéros des objets porteursPropage ObjectStreamWriteException depuis build() en cas d’échec rare de compressionÀ exécuter après l’écriture des objets non éligibles et avant l’émission des références croisées.
ObjStmCompressor::estimateSavingslist<ObjectStreamWriter> $streams, int $originalSizeConstruit chaque flux pour mesurer la taille compressée par rapport à l’originale.ObjStmCompressionResultPropage ObjectStreamWriteException depuis build() en cas d’échec rare de compressionUtilitaire de mesure en lecture seule.
ObjectStreamEntry::__constructint $objectNumber, string $content, int $offsetEnregistrement immuable d’un objet regroupé et de son décalage dans le corps.Ne lève pas d’exceptionfinal readonly ; propriétés publiques.
ObjStmCompressionResult::__constructint $originalObjectCount, int $streamCount, int $estimatedOriginalSize, int $estimatedCompressedSizeConteneur de métriques immuable.Ne lève pas d’exceptionfinal readonly ; propriétés publiques.
ObjStmCompressionResult::savedBytesaucunRenvoie la taille originale moins la taille compressée.intNe lève pas d’exceptionPeut être négatif lorsque le regroupement a augmenté la taille des données.
ObjStmCompressionResult::savedPercentaucunRenvoie la réduction en pourcentage.floatNe lève pas d’exceptionRenvoie 0.0 lorsque la taille originale est nulle.
ObjStmCompressionResult::compressionRatioaucunRenvoie la taille compressée divisée par l’originale.floatNe lève pas d’exceptionRenvoie 1.0 lorsque la taille originale est nulle.
ObjectStreamWriteExceptionSignale un échec de construction d’Object Stream.Étend RuntimeExceptionLevée par build() ; interceptable via RuntimeException pour la rétrocompatibilité.
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;
}

writeRevision écrit une révision par mise à jour incrémentale. Il prend un instantané du préfixe existant du tampon avant l’écriture. Il réécrit le catalogue avec les entrées fusionnées, enregistre les décalages des nouveaux objets, écrit une table de références croisées traditionnelle regroupée en sous-sections contiguës, et écrit un trailer avec /Size, /Root, /Prev et /ID. Après l’écriture, il compare de nouveau le préfixe. Si un octet antérieur a changé, il lève WriterException portant l’état de violation d’ajout seul et ne renvoie aucune sortie exploitable. En cas de succès, il renvoie le décalage en octets de la nouvelle table de références croisées pour enchaîner d’autres révisions. Le mélange de tables et de flux de références croisées d’une révision à l’autre est autorisé.

ObjectStreamWriter accumule des objets. addObject lève une erreur de dépassement lorsque l’index combiné et le corps dépasseraient le maximum de 65,536 octets non compressés. build lève une erreur sur un flux vide ; sinon, il compresse l’index plus le corps et renvoie le contenu de l’Object Stream avec les entrées /Type /ObjStm, /N, /First, /Length et /Filter /FlateDecode. L’appelant attribue le numéro d’objet et ajoute les marqueurs N 0 obj / endobj.

ObjStmCompressor décide quels objets regrouper. Il exclut les objets flux, les dictionnaires de chiffrement, les flux de références croisées, le catalogue du document et tout objet dont le numéro de génération est non nul. writeToBuffer alloue un objet porteur par flux, enregistre chaque objet regroupé comme une entrée de références croisées compressée de type 2, et écrit le bloc ObjStm au décalage courant du tampon. estimateSavings construit chaque flux pour calculer les métriques de taille sans modifier le tampon.

  • La vérification d’ajout seul copie le préfixe existant. Son coût croît avec la taille du document déjà écrit. Ce coût est intentionnel et protège les octets signés.
  • La limite de l’Object Stream s’applique à l’index plus le corps non compressés. Place le dictionnaire de chiffrement et les autres types d’objets exclus en tant qu’objets indirects directs.
  • L’exclusion /Type tolère les espaces arbitraires entre jetons et l’échappement hexadécimal #xx. Des formes telles que /Type /Encrypt, /Type\n/Encrypt et /Type /#45ncrypt sont toutes rejetées, pas seulement l’orthographe littérale canonique.
  • Tout objet portant un numéro de génération non nul est considéré comme non éligible et passe à la sérialisation normale N G obj … endobj, car la génération d’un objet compressé est implicitement nulle.
  • writeToBuffer doit s’exécuter après l’écriture de tous les objets non éligibles et avant l’émission des références croisées. Les objets regroupés ne doivent pas être aussi sérialisés séparément.

Le module Writer n’effectue aucune opération cryptographique. Il protège les octets signés en refusant d’émettre lorsqu’un octet antérieur changerait, ce qui est un test d’égalité octet pour octet plutôt qu’un test cryptographique. La sélection des algorithmes FIPS pour la signature et le hachage est régie par le module de signature, et non par ce writer. Activer ou désactiver le mode FIPS ne change le comportement d’aucune méthode de Writer.

NextPDF implémente le module conformément à ISO 32000-2:2020. Le writer incrémental suit la grammaire de mise à jour incrémentale du §7.5.6 : chaque révision ajoute une section de références croisées couvrant uniquement les objets nouveaux, modifiés ou supprimés, et un trailer dont l’entrée /Prev donne le décalage des références croisées précédentes. Le constructeur d’Object Stream suit le modèle d’object stream du §7.5.7 : un index de paires numéro d’objet / décalage, dont les décalages sont mesurés à partir de l’entrée /First par ordre croissant, précède les corps des objets regroupés. Les deux références de clause ont été vérifiées par rapport au corpus ISO 32000-2:2020. L’enchaînement des révisions pour les workflows PAdES B-LT et B-LTA suit ETSI EN 319 142-1 §5.4, comme annoté dans le code source. La prise en charge d’une clause est une déclaration de capacité d’ingénierie, pas une certification ; NextPDF ne détient aucune certification de conformité formelle.

  • Installe le paquet avec composer require nextpdf/pro:^3. Les classes se résolvent sous NextPDF\Pro\Writer.
  • IncrementalUpdateWriter::writeRevision est un point d’entrée statique ; il ne conserve aucun état d’instance entre les révisions.
  • ObjectStreamEntry, ObjStmCompressionResult, IncrementalUpdateWriter et le compresseur forment ensemble la surface publique du module ; le dépôt ne fournit aucun exemple exécutable pour celui-ci.
  • Une WriterException provenant de writeRevision indique une violation d’ajout seul. Traite-la comme un échec bloquant et abandonne le tampon.
  • Les objets porteurs d’Object Stream sont des objets indirects ; l’appelant attribue leurs numéros d’objet via le registre.

Cette page documente uniquement le comportement observable de l’extérieur et la surface d’API publique prise en charge. Les chemins d’espaces de noms internes, les classes utilitaires, les tables de mécanismes, les noms de fichiers de runbook et les préfixes de tickets sont hors périmètre.