Pro édition
Document — Référence détaillée
Le module Document fournit trois primitives d’assemblage Pro : le découpage par plage de pages, la fusion multi-documents et la construction du dictionnaire PDF Portfolio (Collection). PdfSplitter extrait des plages de pages vers des PDF autonomes et structurellement conformes, et fusionne des documents entiers en un seul fichier renuméroté. PdfPortfolio construit le dictionnaire Collection qui présente les fichiers embarqués avec des colonnes de schéma triables. Chaque point d’entrée borne la taille des entrées et le nombre d’objets contre les entrées hostiles.
Disponibilité et licence
Section intitulée « Disponibilité et licence »Cette fonctionnalité est fournie dans NextPDF Pro (nextpdf/pro) et s’active avec une enveloppe de licence de niveau Pro. Un déploiement dépourvu de ce droit ne charge pas les classes de la fonctionnalité. Comparer les éditions et obtenir une licence.
Surface de l’API publique
Section intitulée « Surface de l’API publique »Tous les types du module résident dans l’espace de noms NextPDF\Pro\Document. PageRange et MergeResult sont des objets-valeurs Core issus de NextPDF\Document.
| Symbole | Paramètres | Comportement par défaut | Renvoie | Lève ou échoue avec | Notes |
|---|---|---|---|---|---|
PdfSplitter::split() | string $pdfData, list<PageRange> $ranges, int $maxBytes = 100_000_000, int $maxRanges = 1000 | Construit un segment PDF autonome par plage | SplitResult | InvalidArgumentException en l’absence d’en-tête %PDF ; OverflowException sur la garde de taille, de nombre de plages ou de fermeture | Les gardes s’exécutent avant toute analyse |
PdfSplitter::splitEvery() | string $pdfData, int $pagesPerSegment | Dérive des plages contiguës de N pages ; le dernier segment peut être plus court | SplitResult | InvalidArgumentException lorsque $pagesPerSegment < 1 ou que l’en-tête est absent | Délègue à split() avec les plafonds par défaut |
PdfSplitter::extractPages() | string $pdfData, PageRange $range | Renvoie une plage sous forme d’octets PDF autonomes | string | InvalidArgumentException en l’absence d’en-tête ; OverflowException sur la garde de fermeture | Aucun paramètre de plafond sur ce chemin |
PdfSplitter::mergeDocuments() | list<string> $pdfs, int $maxInputs = 100, int $maxBytesEach = 100_000_000 | Fusionne les entrées dans l’ordre en un seul PDF renuméroté | MergeResult | InvalidArgumentException sur une liste vide ou une entrée non-PDF ; OverflowException sur le nombre, la taille par entrée ou la garde de fermeture | Depuis 3.1.0 ; la version d’entrée la plus élevée fixe l’en-tête de sortie |
SplitResult | readonly $segments, $ranges, $totalPages | Porte les octets bruts des segments ainsi que les métadonnées source | — | — | Objet-valeur final readonly |
SplitResult::count() | — | Compte les segments produits | int | — | — |
SplitResult::segment() | int $index | Renvoie les octets d’un segment | string | OutOfRangeException sur un index hors limites | Index base zéro |
PdfPortfolio::__construct() | string $viewMode = 'tile' | Valide le mode d’affichage à la construction | — | InvalidArgumentException sur un mode autre que tile, detail, hidden | — |
PdfPortfolio::addSchema() | PortfolioField $field | Ajoute une colonne de schéma | self | — | Fluide |
PdfPortfolio::addEntry() | PortfolioEntry $entry | Ajoute une entrée de fichier | self | — | Fluide |
PdfPortfolio::getSchema() | — | Renvoie les champs de schéma accumulés | list<PortfolioField> | — | — |
PdfPortfolio::getEntries() | — | Renvoie les entrées de fichier accumulées | list<PortfolioEntry> | — | — |
PdfPortfolio::count() | — | Compte les entrées de fichier | int | — | — |
PdfPortfolio::generateCollectionDictionary() | — | Émet la chaîne du dictionnaire Collection | string | — | Les blocs de schéma et de tri n’apparaissent que lorsque des champs existent |
PortfolioEntry | $filename, $data, $description = '', $mimeType = 'application/octet-stream', $customFields = [] | Objet-valeur d’entrée de fichier immuable | — | — | size() renvoie la longueur en octets des données |
PortfolioField | $name, PortfolioFieldType $type, $displayName = '', $order = 0, $visible = true | Objet-valeur de colonne de schéma immuable | — | — | effectiveDisplayName() retombe sur $name |
PortfolioFieldType | Énumération de chaînes : Text, Date, Number, FileName, Description, Size, ModDate, CreationDate | Associe chaque cas à un /Subtype PDF via pdfSubtype() | string (S, D, N, F, Desc) | — | Les cas de type date partagent le sous-type D ; les cas numériques partagent N |
Signatures des points d’entrée :
public function split(string $pdfData, array $ranges, int $maxBytes = 100_000_000, int $maxRanges = 1000): SplitResult
public function mergeDocuments( array $pdfs, int $maxInputs = 100, int $maxBytesEach = 100_000_000,): MergeResultpublic function __construct( private readonly string $viewMode = 'tile',)
public function generateCollectionDictionary(): stringContrat de comportement
Section intitulée « Contrat de comportement »Le découpage et la fusion partagent un même pipeline de graphe d’objets :
- L’entrée doit commencer par l’en-tête
%PDF. Les gardes de taille et de nombre s’exécutent avant l’analyse et lèventOverflowExceptionen cas de dépassement. - Les pages feuilles sont détectées en recherchant les marqueurs d’objet page ; les nœuds de l’arbre des pages sont exclus du décompte.
- L’analyseur indexe chaque objet indirect non compressé au moyen d’un balayage de terminateur tenant compte des flux. La première occurrence d’un identifiant d’objet l’emporte, de sorte que les remplacements par mise à jour incrémentale ne sont pas appliqués.
- Les attributs héritables de l’arbre des pages (
/Resources,/MediaBox,/CropBox,/Rotate) sont matérialisés sur chaque page extraite en parcourant sa chaîne/Parent, de sorte que les segments sont autonomes. - La fermeture transitive des références indirectes de chaque page est collectée, à l’exclusion de l’arête retour
/Parent, puis renumérotée dans un nouvel espace d’identifiants contigu. - Le sérialiseur émet l’en-tête, le Catalog, l’arbre Pages, les objets page et les objets de fermeture, puis une table de références croisées avec des décalages exacts à l’octet et un
startxrefpointant vers le mot-cléxref. mergeDocumentsrépète le pipeline pour chaque entrée dans un espace d’identifiants partagé. La version PDF d’entrée la plus élevée fixe l’en-tête de sortie. C’est le remplacement conforme du fusionneur Core désactivé, qui reste fail-closed.- La sortie est déterministe. Aucun horodatage ni identifiant aléatoire n’est émis, si bien qu’une entrée identique produit des octets identiques.
Assemblage du Portfolio :
- Le constructeur valide le mode d’affichage. Le jeton
/Viewémis est/T,/Dou/Hpour tile, detail et hidden respectivement. generateCollectionDictionary()émet/Type /Collection, le jeton/View, un bloc/Schemalorsque des champs existent et une directive/Sortsur le premier champ de schéma, en ordre croissant.- Chaque champ de schéma émet
/Subtype(issu depdfSubtype()),/N(nom d’affichage échappé),/O(ordre) et/V(visibilité). - Les noms de champ sont assainis en jetons de nom PDF valides ; les caractères non alphanumériques deviennent des tirets bas. Les valeurs de chaîne sont échappées en chaînes littérales PDF.
- Les entrées de fichier sont exposées via
getEntries()pour être embarquées par la couche d’écriture. Le dictionnaire Collection lui-même ne porte que la vue, le schéma et le tri.
Cas limites et modes de défaillance
Section intitulée « Cas limites et modes de défaillance »- Une plage qui ne correspond à aucune page produit un segment minimal d’une page (MediaBox 612 x 792), et non une erreur.
- Un document sans marqueur de page détectable est compté comme une page.
- Les pages stockées dans des flux d’objets ne sont pas détectées ; seuls les objets indirects non compressés participent à l’extraction.
- En présence d’identifiants d’objet en double, la révision de plus faible décalage est utilisée ; les révisions ultérieures issues de mises à jour incrémentales sont ignorées.
- La fermeture des références par segment est plafonnée à 50,000 objets ; un graphe malveillamment auto-référentiel ou à fort éventail lève
OverflowException. - Plafonds par défaut : 100 MB d’entrée, 1,000 plages, 100 entrées de fusion. Tous sont ajustables par l’appelant à chaque appel.
splitEvery()rejette une taille de segment inférieure à 1 avecInvalidArgumentException.SplitResult::segment()rejette un index hors limites avecOutOfRangeException.- Deux noms de champ de schéma qui ne diffèrent que par la ponctuation sont assainis vers la même clé de dictionnaire ; le champ ultérieur masque silencieusement le précédent dans le schéma émis.
- Ce module n’effectue aucune opération cryptographique ; le mode FIPS ne modifie pas son comportement.
Conformité
Section intitulée « Conformité »La sortie des segments et de la fusion suit le modèle d’objet page d’ISO 32000-2 ; la source annote les clauses pertinentes. Affirmations vérifiables de l’extérieur :
- La disposition du trailer, le décalage d’octet
startxrefet le terminateur%%EOFsuivent ISO 32000-2:2020, §7.5.5 — référenceef0f2a4b563b84f81b3e6428612bc47c510d94fc8096849d339abf0f3247d845. - Les valeurs
/Viewdu dictionnaire Collection (/T,/D,/H) suivent ISO 32000-2:2020, §12.3.5 — référence5cefaaeb40f3ff98e3aba135ac57c9424a05c43144c1b9b5156bfd4295e08ddd. - Les entrées
/Subtype,/N,/Oet/Vdu champ Collection suivent ISO 32000-2:2020, §12.3.5 (dictionnaire de champ de collection) — référence6300fbfdc8a913a8dc6f6ae34eff99f2bd03c4313a77777cdd5a8dd856d9537a.
Ces énoncés décrivent une capacité implémentée et vérifiée par les tests du module. La prise en charge d’une construction n’est pas une affirmation de conformité, et la conformité n’est pas une certification ; NextPDF ne détient aucune certification tierce pour ce module.
Notes de développement
Section intitulée « Notes de développement »- Toutes les classes du module sont
final; les types de résultat et d’objet-valeur sontreadonly. Les types splitter et Portfolio datent de 1.9.0 ;mergeDocuments()a été ajouté en 3.1.0. PageRangeetMergeResultsont des types Core, de sorte que les sites d’appel restent portables entre éditions.- Les trailers de segment ne portent que
/Sizeet/Root; aucun identifiant de fichier/IDni dictionnaire/Infon’est émis. - Pour les flux de mise à jour incrémentale ou de signature, confie les octets de segment au module Writer plutôt que de les post-éditer sur place.
- Le module ne journalise aucun contenu de document.
Périmètre de publication
Section intitulée « Périmètre de publication »Cette page documente uniquement le comportement observable de l’extérieur et la surface publique d’API 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.