A PDF is a container: embedded files and associated data
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
At a glance
Section titled “At a glance”Most people picture a PDF as a stack of pages. That is the part you see. But a PDF is also a container, and it can carry whole other files inside it — a spreadsheet, an XML payload, the original source document — bundled into the same single file you hand to someone else.
This page explains how that works: the embedded-file stream that stores the bytes, the name tree that lists them, and the one key that decides whether an attachment is just sitting there or actually means something.
Why this matters
Section titled “Why this matters”An untyped attachment and a typed one look identical to a human. Both are a file riding inside a PDF, and — in this engine — both are associated with the document. The difference is that one of them tells a machine what it is for, and the other leaves the relationship blank for the machine to guess.
That difference is the whole ballgame for a hybrid e-invoice. A tax platform does not read your invoice page; it reads the XML you embedded. If that XML is attached as an undifferentiated blob rather than as the invoice data for the visible document, a conformant reader has no reliable way to know it is the payload to process. The page looks perfect. The invoice gets rejected. The failure arrives days later, with a held payment behind it.
Getting the relationship right, in the layer that produces the file, is far cheaper than discovering it one rejected invoice at a time.
The short version
Section titled “The short version”- A PDF can embed the bytes of any file as an embedded file stream (Spec: ISO 32000-2, §7.11.4ISO 32000-2 §7.11.4). The stream carries the data plus a small parameters dictionary: original size, dates, and a checksum.
- Embedded files are catalogued in the
EmbeddedFilesname tree, so a reader can enumerate them by name without scanning the whole document. - An associated file goes one step further: it declares an
AFRelationship(Spec: ISO 32000-2, §7.11.3ISO 32000-2 §7.11.3) — one of eight standard values (Source,Data,Alternative,Supplement,EncryptedPayload,FormData,Schema,Unspecified), or a custom value — saying how the file relates to the content it is attached to. - That typed relationship is the mechanism behind hybrid e-invoices (ZUGFeRD / Factur-X) and PDF/A-3 attachments (Spec: ISO 19005-3, PDF/A-3ISO 19005-3 PDF/A-3).
- NextPDF supports the raw container primitives in core:
embedFile()andembedFileFromString()with an explicit relationship. Advanced editions add the dedicated EN 16931 / ZUGFeRD / Factur-X e-invoice embedder on top of these primitives.
How NextPDF approaches it
Section titled “How NextPDF approaches it”Think of it as two layers stacked on top of each other.
The lower layer is storage. An embedded file stream
(Spec: ISO 32000-2, §7.11.4ISO 32000-2 §7.11.4) is the bytes of the original
file wrapped in a PDF stream object, with a parameters dictionary recording the
original size, modification date, and a checksum of the uncompressed data. The
stream is reached through a file specification dictionary whose /EF
dictionary points to the embedded file stream — the stream itself does not carry
/EF. A reader can pull the file back out byte-for-byte. To make these files
findable, the document catalog holds an
EmbeddedFiles name tree — a sorted map from a name to each file
specification — so a viewer can list “here are the 3 files inside this PDF”
without walking every page.
The upper layer is meaning. By itself, an embedded file is just present.
The associated-files mechanism (Spec: ISO 32000-2, §14.13ISO 32000-2 §14.13)
attaches a file to something — the whole document, a page, a graphics object —
and stamps it with an AFRelationship. ISO 32000-2 defines a small vocabulary
of eight standard values (Spec: ISO 32000-2, §7.11.3ISO 32000-2 §7.11.3),
and permits custom values too; each standard value answers a precise question:
AFRelationship | What it asserts about the file |
|---|---|
Source | This is the source material the visible content was generated from (for example, the original word-processor document). |
Data | This is structured data tied to the visible content — the canonical case is the invoice XML behind a rendered invoice page. |
Alternative | This is an alternative representation of the same content (for example, an audio or video version). |
Supplement | This is supplemental material that extends the content but is not part of it. |
EncryptedPayload | The embedded file is an encrypted payload that the PDF wraps as an opaque blob. |
FormData | The file is form data (FDF, XFDF, or an XML form payload). |
Schema | The file is a schema describing the structure of a Data file (for example, an XSD for XML data or a JSON Schema). |
Unspecified | The relationship is deliberately not stated. Honest, but it tells a machine nothing. |
Beyond these eight, the standard also permits application-specific custom relationship values, so the vocabulary is extensible rather than fixed.
An associated file is defined by two things working together, not one key
alone. The /AF association binds the file specification to a part of the
document; the AFRelationship key in the file specification then states the
semantic relationship. The /AF entry on the association point (the document
catalog, a page, or an object) is an array — that array contains one or more
file specification dictionaries, usually as indirect references; /AF is not a
single reference. A document-level associated file is the file specification
listed in the document catalog’s /AF array, carrying its AFRelationship. Mark
that spreadsheet Unspecified and you have associated it with the document but
told a machine nothing about why. Mark the same spreadsheet Data and you have
told every conforming reader what it is and what it is for. The bytes are the
same. The semantics are not.
This is why the e-invoice case is not “attach an XML file”. It is “embed this
XML as the Data associated file for this document, inside a conforming PDF/A-3
carrier” — with invoice validity and legal acceptance remaining separate checks
the carrier does not perform. The flow has four stages, and the order is what
keeps it 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).
That fourth stage is why PDF/A-3 exists as a distinct profile. Earlier
archival profiles restricted what could be embedded; PDF/A-3
(Spec: ISO 19005-3, PDF/A-3ISO 19005-3 PDF/A-3) is the part that permits
files of any format to ride inside a conforming archival document. It permits
the embedded payload — it does not validate that payload or confer legal status.
Without it, the hybrid invoice — one file that is both the page a person reads
and the data a tax system parses — could not be a conforming archival PDF/A
document at all; whether the invoice is valid and legally accepted remains a
separate question. The dedicated e-invoice embedder that Advanced editions
add is the convenience seam over exactly this: it embeds the payload, sets the
relationship to Data, and registers it correctly, so you do not assemble the
container plumbing by hand. The deeper invoicing and archival mechanics live on
the two neighbouring pages linked below; this page is about the container they
both stand on.
Practical example
Section titled “Practical example”A small, complete program. The two calls that matter are the difference
between an untyped associated file and a typed one — and the relationship is
an explicit argument you should set. In this engine, both calls produce an
associated file: embedFile() and embedFileFromString() always register the
file specification in the document catalog’s /AF array, so the only thing the
relationship changes is what the association means. It defaults to
Unspecified, which associates the file but tells a machine nothing about why;
for an e-invoice payload you set it to Data so a reader can find it.
<?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();The '/Data' relationship is unmistakable. The first attachment — left
Unspecified — is associated all the same, just without a stated meaning. For
both calls the engine writes the embedded file stream, adds the file to the
EmbeddedFiles name tree, lists its file specification in the document catalog’s
/AF array, and records the relationship you stated — it does not pick one for
you. This engine has no name-tree-only mode: every file you embed this way is a
document-associated file, so the relationship is the only lever you control.
Common misconception
Section titled “Common misconception”The frequent assumption is that “embedded” and “associated” are two words for
the same thing. They are not. Embedded is about storage — the bytes are inside
the PDF. Associated is about binding — the file specification is listed in an
/AF array on a part of the document, and it carries an AFRelationship. In the
abstract PDF model a file can be embedded into the name tree without ever being
associated; NextPDF’s embedFile() path does not leave it there — it always
writes the /AF association — so for this engine the open question is never
whether a file is associated but what the relationship says.
A second trap: assuming a viewer will “figure out” which attachment is the
invoice. A conforming reader is not supposed to guess. It looks for the file
whose relationship says Data. Leave the relationship Unspecified and you have
associated the payload while telling the machine nothing useful about its role.
Limits and boundaries
Section titled “Limits and boundaries”The container mechanism is powerful in a way that is worth being honest about:
embedFile() reads whatever path the PHP process can read. That is the
feature — and it is also the boundary. The engine attaches the bytes it is
given; it does not, and cannot, decide for you whether a path is one you
intended to expose.
| Edition | Availability |
|---|---|
| Core |
|
| Pro | Not in this edition |
| Enterprise | Not in this edition |
Two further limits worth stating plainly:
- Embedding is not validating. The engine carries the bytes you give it. Whether the embedded XML is a conformant invoice payload is a separate question, answered by a validator — see the invoicing page.
- A typed attachment is not a conformant archival file on its own. Making the hybrid file a legal PDF/A-3 document requires the archival mode and an independent conformance check — see the archival page.
Related docs
Section titled “Related docs”- Invoices and e-invoicing — the
use case this mechanism makes possible: a hybrid PDF that carries a
machine-readable invoice as its
Dataassociated file. - Archival and PDF/A — why the carrier is a PDF/A-3 file and what conformance does and does not promise.
- The anatomy of a PDF file — where the name tree and the document catalog sit in the file structure.
- Streams and filters — how the bytes of an embedded file are stored and compressed inside a stream object.
Glossary
Section titled “Glossary”- Embedded file stream — a PDF stream object holding the bytes of an external file, with a parameters dictionary recording its original size, dates, and a checksum (ISO 32000-2 §7.11.4).
- EmbeddedFiles name tree — the sorted map in the document catalog that lists embedded files by name, so a reader can enumerate attachments without scanning the whole document.
- Associated file — an embedded file bound to a part of the document by an
/AFassociation (on the document catalog, a page, or an object) and carrying anAFRelationshipthat states how it relates to that content; the document-level case — the file specification in the catalog’s/AFarray — is the one this page centres on (ISO 32000-2 §14.13.3). - AFRelationship — the file-specification key whose value names the
relationship (ISO 32000-2 §7.11.3). It takes one of eight standard values
(
Source,Data,Alternative,Supplement,EncryptedPayload,FormData,Schema,Unspecified) or a custom value;Datais the value a hybrid e-invoice payload uses. - PDF/A-3 — the ISO 19005-3 archival profile that permits files of any format to be embedded, enabling a conforming hybrid document.
- Hybrid invoice — one PDF file that is both a human-readable page and a machine-readable embedded invoice payload.