Skip to content
getnextpdf.com

A PDF is a container: embedded files and associated data

Spec: ISO 32000-2, §7.11.4Spec: ISO 32000-2, §14.13Spec: ISO 19005-3, PDF/A-3

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.

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.

  • A PDF can embed the bytes of any file as an embedded file stream (Spec: ISO 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 EmbeddedFiles name 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.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-3).
  • NextPDF supports the raw container primitives in core: embedFile() and embedFileFromString() with an explicit relationship. Advanced editions add the dedicated EN 16931 / ZUGFeRD / Factur-X e-invoice embedder on top of these primitives.

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.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.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.3), and permits custom values too; each standard value answers a precise question:

AFRelationshipWhat it asserts about the file
SourceThis is the source material the visible content was generated from (for example, the original word-processor document).
DataThis is structured data tied to the visible content — the canonical case is the invoice XML behind a rendered invoice page.
AlternativeThis is an alternative representation of the same content (for example, an audio or video version).
SupplementThis is supplemental material that extends the content but is not part of it.
EncryptedPayloadThe embedded file is an encrypted payload that the PDF wraps as an opaque blob.
FormDataThe file is form data (FDF, XFDF, or an XML form payload).
SchemaThe file is a schema describing the structure of a Data file (for example, an XSD for XML data or a JSON Schema).
UnspecifiedThe 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.

  1. Store the bytesThe file is wrapped in an embedded file stream with its size, dates, and a checksum (ISO 32000-2 §7.11.4).
  2. Register it by nameThe file specification is added to the EmbeddedFiles name tree so a reader can enumerate attachments without scanning the document.
  3. 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).
  4. 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).
How a typed attachment becomes a hybrid file end to end: the engine stores the bytes, registers the file by name, declares the relationship, and the archival profile permits it all to ride inside one conforming archival document.

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-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.

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.

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.

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.

Embedding a file from a caller-supplied path — edition availability
EditionAvailability
Core

embedFile() reads any path the PHP process has access to and embeds its bytes verbatim. Validating that the path is safe and intended — not a user-controlled value, a traversal, or a secret outside the document’s scope — is the integrator’s responsibility. This is a documented security contract, not an oversight: the engine will not silently guess which paths are legitimate, because that guess belongs to your application, which knows the trust boundary the engine cannot see. Pass attacker-influenced bytes through a string with embedFileFromString() so the path layer is never in play.

ProNot in this edition
EnterpriseNot 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.
  • Invoices and e-invoicing — the use case this mechanism makes possible: a hybrid PDF that carries a machine-readable invoice as its Data associated 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.
  • 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 /AF association (on the document catalog, a page, or an object) and carrying an AFRelationship that states how it relates to that content; the document-level case — the file specification in the catalog’s /AF array — 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; Data is 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.