Un PDF est un conteneur : fichiers incorporés et données associées
Spec: ISO 32000-2, §7.11.4ISO 32000-2 §7.11.4Spec: ISO 32000-2, §14.13ISO 32000-2 §14.13Spec: ISO 19005-3, PDF/A-3ISO 19005-3 PDF/A-3
La plupart des gens imaginent un PDF comme une pile de pages. C’est la partie que tu vois. Mais un PDF est aussi un conteneur, et il peut transporter d’autres fichiers entiers en son sein — un tableur, une charge utile XML, le document source d’origine — regroupés dans le même fichier unique que tu remets à quelqu’un d’autre.
Cette page explique comment cela fonctionne : le flux de fichier incorporé qui stocke les octets, l’arbre de noms qui les répertorie, et la seule clé qui décide si une pièce jointe est simplement posée là ou si elle signifie réellement quelque chose.
Pourquoi c’est important
Section intitulée « Pourquoi c’est important »Une pièce jointe non typée et une pièce jointe typée sont identiques pour un humain. Toutes deux sont un fichier voyageant à l’intérieur d’un PDF et — dans ce moteur — toutes deux sont associées au document. La différence, c’est que l’une d’elles indique à une machine à quoi elle sert, tandis que l’autre laisse la relation vierge pour que la machine devine.
Cette différence est tout l’enjeu pour une facture électronique hybride. Une plateforme fiscale ne lit pas la page de ta facture ; elle lit le XML que tu as incorporé. Si ce XML est joint comme un bloc indifférencié plutôt que comme les données de facture du document visible, un lecteur conforme n’a aucun moyen fiable de savoir que c’est la charge utile à traiter. La page a l’air parfaite. La facture est rejetée. L’échec arrive des jours plus tard, avec un paiement bloqué derrière lui.
Bien établir la relation, dans la couche qui produit le fichier, revient bien moins cher que de la découvrir une facture rejetée à la fois.
La version courte
Section intitulée « La version courte »- Un PDF peut incorporer les octets de n’importe quel fichier sous forme de flux de fichier incorporé (Spec: ISO 32000-2, §7.11.4ISO 32000-2 §7.11.4). Le flux porte les données plus un petit dictionnaire de paramètres : taille d’origine, dates et somme de contrôle.
- Les fichiers incorporés sont catalogués dans l’arbre de noms
EmbeddedFiles, de sorte qu’un lecteur peut les énumérer par nom sans parcourir tout le document. - Un fichier associé va un pas plus loin : il déclare une
AFRelationship(Spec: ISO 32000-2, §7.11.3ISO 32000-2 §7.11.3) — l’une de huit valeurs standard (Source,Data,Alternative,Supplement,EncryptedPayload,FormData,Schema,Unspecified), ou une valeur personnalisée — précisant comment le fichier se rapporte au contenu auquel il est joint. - Cette relation typée est le mécanisme derrière les factures électroniques hybrides (ZUGFeRD / Factur-X) et les pièces jointes PDF/A-3 (Spec: ISO 19005-3, PDF/A-3ISO 19005-3 PDF/A-3).
- NextPDF prend en charge les primitives brutes du conteneur dans le core :
embedFile()etembedFileFromString()avec une relation explicite. Les éditions Advanced ajoutent par-dessus ces primitives l’incorporateur de factures électroniques EN 16931 / ZUGFeRD / Factur-X dédié.
L’approche de NextPDF
Section intitulée « L’approche de NextPDF »Considère cela comme deux couches empilées l’une sur l’autre.
La couche inférieure est le stockage. Un flux de fichier incorporé
(Spec: ISO 32000-2, §7.11.4ISO 32000-2 §7.11.4) correspond aux octets du fichier
d’origine enveloppés dans un objet flux PDF, avec un dictionnaire de paramètres
enregistrant la taille d’origine, la date de modification et une somme de contrôle
des données non compressées. On accède au flux via un dictionnaire de spécification
de fichier dont le dictionnaire /EF pointe vers le flux de fichier incorporé — le
flux lui-même ne porte pas /EF. Un lecteur peut ressortir le fichier octet pour
octet. Pour rendre ces fichiers repérables, le catalogue du document détient un
arbre de noms EmbeddedFiles — une carte triée d’un nom vers chaque spécification de
fichier — afin qu’un lecteur puisse lister « voici les 3 fichiers à l’intérieur de
ce PDF » sans parcourir chaque page.
La couche supérieure est le sens. À elle seule, une pièce incorporée est
simplement présente. Le mécanisme des fichiers associés
(Spec: ISO 32000-2, §14.13ISO 32000-2 §14.13) attache un fichier à quelque chose
— le document entier, une page, un objet graphique — et l’estampille d’une
AFRelationship. ISO 32000-2 définit un petit vocabulaire de huit valeurs standard
(Spec: ISO 32000-2, §7.11.3ISO 32000-2 §7.11.3), et permet aussi des valeurs
personnalisées ; chaque valeur standard répond à une question précise :
AFRelationship | Ce qu’elle affirme à propos du fichier |
|---|---|
Source | C’est le matériau source à partir duquel le contenu visible a été généré (par exemple, le document de traitement de texte d’origine). |
Data | Ce sont des données structurées liées au contenu visible — le cas canonique étant le XML de facture derrière une page de facture rendue. |
Alternative | C’est une représentation alternative du même contenu (par exemple, une version audio ou vidéo). |
Supplement | C’est un matériau supplémentaire qui étend le contenu mais n’en fait pas partie. |
EncryptedPayload | Le fichier incorporé est une charge utile chiffrée que le PDF enveloppe comme un bloc opaque. |
FormData | Le fichier est constitué de données de formulaire (FDF, XFDF ou une charge utile de formulaire XML). |
Schema | Le fichier est un schéma décrivant la structure d’un fichier Data (par exemple, un XSD pour des données XML ou un JSON Schema). |
Unspecified | La relation n’est délibérément pas indiquée. Honnête, mais cela ne dit rien à une machine. |
Au-delà de ces huit, la norme permet également des valeurs de relation personnalisées spécifiques à l’application, de sorte que le vocabulaire est extensible plutôt que figé.
Un fichier associé est défini par deux choses qui fonctionnent ensemble, pas une
clé seule. L’association /AF lie la spécification de fichier à une partie du
document ; la clé AFRelationship dans la spécification de fichier énonce alors
la relation sémantique. L’entrée /AF au point d’association (le catalogue du
document, une page ou un objet) est un tableau — ce tableau contient une ou
plusieurs spécifications de fichier, généralement sous forme de références
indirectes ; /AF n’est pas une référence unique. Un fichier associé au niveau
document est la spécification de fichier listée dans le tableau /AF du catalogue
du document, portant son AFRelationship. Marque ce tableur Unspecified et tu
l’as associé au document mais tu n’as rien dit à une machine sur le pourquoi.
Marque le même tableur Data et tu as dit à chaque lecteur conforme ce qu’il est
et à quoi il sert. Les octets sont les mêmes. La sémantique, non.
C’est pourquoi le cas de la facture électronique n’est pas « joins un fichier
XML ». C’est « incorpore ce XML comme le fichier associé Data de ce document, à
l’intérieur d’un porteur PDF/A-3 conforme » — la validité de la facture et
l’acceptation légale demeurant des contrôles distincts que le porteur n’effectue
pas. Le flux comporte quatre étapes, et c’est l’ordre qui le maintient correct.
- Store the bytesThe file is wrapped in an embedded file stream with its size, dates, and a checksum (ISO 32000-2 §7.11.4).
- Register it by nameThe file specification is added to the EmbeddedFiles name tree so a reader can enumerate attachments without scanning the document.
- Declare the relationshipAn AFRelationship value (one of the eight standard values such as Source or Data) marks how the file relates to the content, associated at the document level (ISO 32000-2 §14.13.3).
- Make it archivalA PDF/A-3 carrier permits the embedded payload to ride inside one conforming archival PDF/A document; invoice validity and legal acceptance remain separate checks (ISO 19005-3).
Cette quatrième étape explique pourquoi PDF/A-3 existe comme profil distinct. Les
profils d’archivage antérieurs restreignaient ce qui pouvait être incorporé ;
PDF/A-3 (Spec: ISO 19005-3, PDF/A-3ISO 19005-3 PDF/A-3) est la partie qui permet
à des fichiers de n’importe quel format de voyager à l’intérieur d’un document
d’archivage conforme. Il permet la charge utile incorporée — il ne valide pas cette
charge utile et ne confère pas de statut légal. Sans lui, la facture hybride — un
fichier qui est à la fois la page qu’une personne lit et les données qu’un système
fiscal analyse — ne pourrait pas être du tout un document d’archivage PDF/A conforme ;
savoir si la facture est valide et légalement acceptée demeure une question
distincte. L’incorporateur de factures électroniques dédié que les éditions
Advanced ajoutent est la couture de commodité par-dessus exactement cela : il
incorpore la charge utile, fixe la relation à Data et l’enregistre correctement,
pour que tu n’assembles pas à la main la plomberie du conteneur. Les mécaniques plus
profondes de la facturation et de l’archivage vivent sur les deux pages voisines
liées ci-dessous ; cette page porte sur le conteneur sur lequel elles reposent
toutes deux.
Exemple pratique
Section intitulée « Exemple pratique »Un petit programme complet. Les deux appels qui comptent sont la différence entre
un fichier associé non typé et un fichier associé typé — et la relation est un
argument explicite que tu devrais définir. Dans ce moteur, les deux appels
produisent un fichier associé : embedFile() et embedFileFromString() enregistrent
toujours la spécification de fichier dans le tableau /AF du catalogue du document,
de sorte que la seule chose que la relation change est ce que l’association
signifie. Elle a pour valeur par défaut Unspecified, qui associe le fichier mais
ne dit rien à une machine sur le pourquoi ; pour une charge utile de facture
électronique, tu la fixes à Data afin qu’un lecteur puisse la trouver.
<?php
declare(strict_types=1);
use NextPDF\Core\Document;use NextPDF\Navigation\AFRelationship;
$document = Document::createStandalone();$document->addPage();$document->setFont('helvetica', 'B', 16);$document->cell(0, 12, 'Invoice INV-2026-0042', newLine: true);
// An UNTYPED associated file: the bytes are embedded AND the file spec is// added to the document catalog's /AF array, but the relationship says// nothing about why. A reader can open it; a machine cannot tell its role.// The relationship is left Unspecified (its default); the second argument is// the human-readable description. embedFile accepts the AFRelationship enum.$document->embedFile( '/srv/invoices/INV-2026-0042-source.docx', 'Original source document', AFRelationship::Unspecified,);
// A TYPED associated file: the invoice XML is declared as the DATA behind// the visible page. This is the relationship a hybrid e-invoice reader// looks for — the same intent the dedicated e-invoice embedder sets.// embedFileFromString takes the data, a filename, a description, and a// relationship as a PDF-name string ('/Data').$invoiceXml = $generateCiiXml(); // your ERP authors this; the engine never does$document->embedFileFromString( $invoiceXml, 'factur-x.xml', 'Factur-X invoice data', '/Data',);
$bytes = $document->getPdfData();La relation '/Data' est sans équivoque. La première pièce jointe — laissée
Unspecified — est tout de même associée, simplement sans signification énoncée.
Pour les deux appels, le moteur écrit le flux de fichier incorporé, ajoute le fichier
à l’arbre de noms EmbeddedFiles, liste sa spécification de fichier dans le tableau
/AF du catalogue du document et enregistre la relation que tu as énoncée — il n’en
choisit pas une à ta place. Ce moteur n’a aucun mode arbre-de-noms-seul : chaque
fichier que tu incorpores de cette manière est un fichier associé au document, de
sorte que la relation est le seul levier que tu contrôles.
Idée fausse courante
Section intitulée « Idée fausse courante »L’hypothèse fréquente est que « incorporé » et « associé » sont deux mots pour la
même chose. Ils ne le sont pas. Incorporé concerne le stockage — les octets sont à
l’intérieur du PDF. Associé concerne la liaison — la spécification de fichier est
listée dans un tableau /AF sur une partie du document, et elle porte une
AFRelationship. Dans le modèle PDF abstrait, un fichier peut être incorporé dans
l’arbre de noms sans jamais être associé ; le chemin embedFile() de NextPDF ne le
laisse pas ainsi — il écrit toujours l’association /AF — de sorte que, pour ce
moteur, la question ouverte n’est jamais si un fichier est associé mais ce que la
relation dit.
Un second piège : supposer qu’un lecteur va « deviner » quelle pièce jointe est la
facture. Un lecteur conforme n’est pas censé deviner. Il cherche le fichier dont la
relation dit Data. Laisse la relation Unspecified et tu as associé la charge
utile tout en ne disant à la machine rien d’utile sur son rôle.
Limites et frontières
Section intitulée « Limites et frontières »Le mécanisme de conteneur est puissant d’une manière qui mérite d’être dite
honnêtement : embedFile() lit n’importe quel chemin que le processus PHP peut
lire. C’est la fonctionnalité — et c’est aussi la frontière. Le moteur attache les
octets qu’on lui donne ; il ne décide pas, et ne peut pas décider, à ta place si un
chemin est un chemin que tu avais l’intention d’exposer.
| Edition | Availability |
|---|---|
| Core |
|
| Pro | Not in this edition |
| Enterprise | Not in this edition |
Deux limites supplémentaires méritent d’être énoncées clairement :
- Incorporer n’est pas valider. Le moteur transporte les octets que tu lui donnes. Savoir si le XML incorporé est une charge utile de facture conforme est une question distincte, à laquelle répond un validateur — vois la page de facturation.
- Une pièce jointe typée n’est pas, à elle seule, un fichier d’archivage conforme. Faire de la facture hybride un document PDF/A-3 légal nécessite le mode d’archivage et un contrôle de conformité indépendant — vois la page d’archivage.
Documents liés
Section intitulée « Documents liés »- Factures et facturation électronique —
le cas d’usage que ce mécanisme rend possible : un PDF hybride qui transporte une
facture lisible par machine comme son fichier associé
Data. - Archivage et PDF/A — pourquoi le porteur est un fichier PDF/A-3 et ce que la conformité promet et ne promet pas.
- L’anatomie d’un fichier PDF — où se situent l’arbre de noms et le catalogue du document dans la structure du fichier.
- Flux et filtres — comment les octets d’un fichier incorporé sont stockés et compressés à l’intérieur d’un objet flux.
Glossaire
Section intitulée « Glossaire »- Flux de fichier incorporé — un objet flux PDF contenant les octets d’un fichier externe, avec un dictionnaire de paramètres enregistrant sa taille d’origine, ses dates et une somme de contrôle (ISO 32000-2 §7.11.4).
- Arbre de noms EmbeddedFiles — la carte triée du catalogue du document qui liste les fichiers incorporés par nom, pour qu’un lecteur puisse énumérer les pièces jointes sans parcourir tout le document.
- Fichier associé — un fichier incorporé lié à une partie du document par une
association
/AF(sur le catalogue du document, une page ou un objet) et portant uneAFRelationshipqui énonce comment il se rapporte à ce contenu ; le cas au niveau document — la spécification de fichier dans le tableau/AFdu catalogue — est celui sur lequel cette page se concentre (ISO 32000-2 §14.13.3). - AFRelationship — la clé de spécification de fichier dont la valeur nomme la
relation (ISO 32000-2 §7.11.3). Elle prend l’une de huit valeurs standard
(
Source,Data,Alternative,Supplement,EncryptedPayload,FormData,Schema,Unspecified) ou une valeur personnalisée ;Dataest la valeur qu’utilise une charge utile de facture électronique hybride. - PDF/A-3 — le profil d’archivage ISO 19005-3 qui permet d’incorporer des fichiers de n’importe quel format, rendant possible un document hybride conforme.
- Facture hybride — un seul fichier PDF qui est à la fois une page lisible par un humain et une charge utile de facture incorporée lisible par machine.