Un PDF es un contenedor: archivos incrustados y datos asociados
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
De un vistazo
Sección titulada «De un vistazo»La mayoría imagina un PDF como una pila de páginas. Esa es la parte que se ve. Pero un PDF es también un contenedor, y puede transportar otros archivos completos dentro de sí —una hoja de cálculo, una carga útil XML, el documento de origen original— agrupados en el mismo archivo único que se entrega a otra persona.
Esta página explica cómo funciona: el flujo de archivo incrustado que almacena los bytes, el árbol de nombres que los lista, y la única clave que decide si un adjunto simplemente está ahí o realmente significa algo.
Por qué importa
Sección titulada «Por qué importa»Un adjunto sin tipo y uno con tipo parecen idénticos a una persona. Ambos son un archivo que viaja dentro de un PDF y —en este motor— ambos están asociados al documento. La diferencia es que uno de ellos le dice a una máquina para qué sirve, y el otro deja la relación en blanco para que la máquina la adivine.
Esa diferencia lo es todo para una factura electrónica híbrida. Una plataforma tributaria no lee la página de su factura; lee el XML que usted incrustó. Si ese XML se adjunta como un bloque indiferenciado en lugar de como los datos de la factura del documento visible, un lector conforme no tiene forma fiable de saber que es la carga útil que debe procesar. La página se ve perfecta. La factura se rechaza. El fallo llega días después, con un pago retenido detrás.
Acertar con la relación, en la capa que produce el archivo, es mucho más barato que descubrirlo de factura rechazada en factura rechazada.
La versión breve
Sección titulada «La versión breve»- Un PDF puede incrustar los bytes de cualquier archivo como un flujo de archivo incrustado (Spec: ISO 32000-2, §7.11.4ISO 32000-2 §7.11.4). El flujo transporta los datos más un pequeño diccionario de parámetros: tamaño original, fechas y una suma de comprobación.
- Los archivos incrustados se catalogan en el árbol de nombres
EmbeddedFiles, de modo que un lector pueda enumerarlos por nombre sin escanear todo el documento. - Un archivo asociado va un paso más allá: declara una
AFRelationship(Spec: ISO 32000-2, §7.11.3ISO 32000-2 §7.11.3) —uno de ocho valores estándar (Source,Data,Alternative,Supplement,EncryptedPayload,FormData,Schema,Unspecified), o un valor personalizado— que indica cómo se relaciona el archivo con el contenido al que se adjunta. - Esa relación tipada es el mecanismo detrás de las facturas electrónicas híbridas (ZUGFeRD / Factur-X) y los adjuntos PDF/A-3 (Spec: ISO 19005-3, PDF/A-3ISO 19005-3 PDF/A-3).
- NextPDF admite en el núcleo las primitivas de contenedor en bruto:
embedFile()yembedFileFromString()con una relación explícita. Las ediciones Advanced añaden el incrustador de facturas electrónicas EN 16931 / ZUGFeRD / Factur-X dedicado, encima de estas primitivas.
Cómo lo aborda NextPDF
Sección titulada «Cómo lo aborda NextPDF»Imagínelo como dos capas apiladas una sobre otra.
La capa inferior es el almacenamiento. Un flujo de archivo incrustado
(Spec: ISO 32000-2, §7.11.4ISO 32000-2 §7.11.4) son los bytes del archivo
original envueltos en un objeto de flujo PDF, con un diccionario de parámetros que
registra el tamaño original, la fecha de modificación y una suma de comprobación de
los datos sin comprimir. Al flujo se llega a través de un diccionario de
especificación de archivo cuyo diccionario /EF apunta al flujo de archivo
incrustado; el flujo en sí no lleva /EF. Un lector puede extraer el archivo de
nuevo byte por byte. Para que estos archivos sean localizables, el catálogo del
documento contiene un árbol de nombres EmbeddedFiles —un mapa ordenado de un
nombre a cada especificación de archivo— de modo que un lector pueda listar «aquí
están los 3 archivos dentro de este PDF» sin recorrer cada página.
La capa superior es el significado. Por sí mismo, un archivo incrustado
simplemente está presente. El mecanismo de archivos asociados
(Spec: ISO 32000-2, §14.13ISO 32000-2 §14.13) adjunta un archivo a algo —el
documento completo, una página, un objeto gráfico— y lo marca con una
AFRelationship. ISO 32000-2 define un pequeño vocabulario de ocho valores estándar
(Spec: ISO 32000-2, §7.11.3ISO 32000-2 §7.11.3), y permite también valores
personalizados; cada valor estándar responde a una pregunta precisa:
AFRelationship | Qué afirma sobre el archivo |
|---|---|
Source | Este es el material de origen a partir del cual se generó el contenido visible (por ejemplo, el documento de procesador de textos original). |
Data | Estos son datos estructurados ligados al contenido visible; el caso canónico es el XML de factura detrás de una página de factura renderizada. |
Alternative | Esta es una representación alternativa del mismo contenido (por ejemplo, una versión de audio o vídeo). |
Supplement | Este es material complementario que amplía el contenido pero no forma parte de él. |
EncryptedPayload | El archivo incrustado es una carga útil cifrada que el PDF envuelve como un bloque opaco. |
FormData | El archivo son datos de formulario (FDF, XFDF o una carga útil de formulario XML). |
Schema | El archivo es un esquema que describe la estructura de un archivo Data (por ejemplo, un XSD para datos XML o un JSON Schema). |
Unspecified | La relación se deja deliberadamente sin indicar. Honesto, pero no le dice nada a una máquina. |
Más allá de estos ocho, el estándar también permite valores de relación personalizados específicos de la aplicación, de modo que el vocabulario es extensible en lugar de fijo.
Un archivo asociado lo definen dos cosas que trabajan juntas, no una sola clave. La
asociación /AF vincula la especificación de archivo a una parte del documento;
la clave AFRelationship en la especificación de archivo después enuncia la
relación semántica. La entrada /AF en el punto de asociación (el catálogo del
documento, una página o un objeto) es un arreglo —ese arreglo contiene una o más
diccionarios de especificación de archivo, normalmente como referencias indirectas;
/AF no es una referencia única—. Un archivo asociado a nivel de documento es la
especificación de archivo listada en el arreglo /AF del catálogo del documento,
con su AFRelationship. Marque esa hoja de cálculo como Unspecified y la habrá
asociado al documento pero no le habrá dicho nada a una máquina sobre el porqué.
Marque la misma hoja de cálculo como Data y le habrá dicho a todo lector conforme
qué es y para qué sirve. Los bytes son los mismos. La semántica no.
Por eso el caso de la factura electrónica no es «adjuntar un archivo XML». Es
«incrustar este XML como el archivo asociado Data de este documento, dentro de un
portador PDF/A-3 conforme», quedando la validez de la factura y la aceptación legal
como comprobaciones separadas que el portador no realiza. El flujo tiene cuatro
etapas, y el orden es lo que lo mantiene correcto.
- 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).
Esa cuarta etapa es la razón por la que PDF/A-3 existe como un perfil distinto. Los
perfiles de archivado anteriores restringían lo que podía incrustarse; PDF/A-3
(Spec: ISO 19005-3, PDF/A-3ISO 19005-3 PDF/A-3) es la parte que permite que
archivos de cualquier formato viajen dentro de un documento de archivado conforme.
Permite la carga útil incrustada; no valida esa carga útil ni confiere estatus
legal. Sin él, la factura híbrida —un único archivo que es a la vez la página que
una persona lee y los datos que un sistema tributario analiza— no podría ser en
absoluto un documento de archivado PDF/A conforme; si la factura es válida y
legalmente aceptada sigue siendo una cuestión separada. El incrustador de facturas
electrónicas dedicado que las ediciones Advanced añaden es la costura de
conveniencia justo sobre esto: incrusta la carga útil, fija la relación en Data y
la registra correctamente, de modo que usted no monte a mano la fontanería del
contenedor. La mecánica más profunda de facturación y archivado vive en las dos
páginas vecinas enlazadas abajo; esta página trata del contenedor sobre el que
ambas se apoyan.
Ejemplo práctico
Sección titulada «Ejemplo práctico»Un programa pequeño y completo. Las dos llamadas que importan son la diferencia
entre un archivo asociado sin tipo y uno con tipo, y la relación es un argumento
explícito que debería establecer. En este motor, ambas llamadas producen un
archivo asociado: embedFile() y embedFileFromString() siempre registran la
especificación de archivo en el arreglo /AF del catálogo del documento, de modo
que lo único que cambia la relación es qué significa la asociación. Su valor
predeterminado es Unspecified, que asocia el archivo pero no le dice nada a una
máquina sobre el porqué; para la carga útil de una factura electrónica se establece
en Data para que un lector pueda encontrarla.
<?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 relación '/Data' es inconfundible. El primer adjunto —dejado como
Unspecified— está asociado igualmente, solo que sin un significado declarado.
Para ambas llamadas el motor escribe el flujo de archivo incrustado, añade el
archivo al árbol de nombres EmbeddedFiles, lista su especificación de archivo en
el arreglo /AF del catálogo del documento y registra la relación que usted
enunció: no elige una por usted. Este motor no tiene un modo de solo árbol de
nombres: cada archivo que incruste de esta forma es un archivo asociado al
documento, de modo que la relación es la única palanca que usted controla.
Concepto erróneo habitual
Sección titulada «Concepto erróneo habitual»La suposición frecuente es que «incrustado» y «asociado» son dos palabras para lo
mismo. No lo son. Incrustado tiene que ver con el almacenamiento: los bytes están
dentro del PDF. Asociado tiene que ver con el vínculo: la especificación de
archivo está listada en un arreglo /AF de una parte del documento, y lleva una
AFRelationship. En el modelo abstracto de PDF un archivo puede incrustarse en el
árbol de nombres sin estar nunca asociado; la ruta embedFile() de NextPDF no lo
deja ahí —siempre escribe la asociación /AF—, de modo que para este motor la
pregunta abierta nunca es si un archivo está asociado, sino qué dice la
relación.
Una segunda trampa: suponer que un lector «averiguará» qué adjunto es la factura.
Un lector conforme no debe adivinar. Busca el archivo cuya relación dice Data.
Deje la relación en Unspecified y habrá asociado la carga útil mientras no le dice
a la máquina nada útil sobre su papel.
Límites y fronteras
Sección titulada «Límites y fronteras»El mecanismo de contenedor es potente de una forma sobre la que conviene ser
honesto: embedFile() lee cualquier ruta que el proceso PHP pueda leer. Esa es la
función, y es también la frontera. El motor adjunta los bytes que se le dan; no
decide por usted, ni puede hacerlo, si una ruta es una que usted pretendía
exponer.
| Edition | Availability |
|---|---|
| Core |
|
| Pro | Not in this edition |
| Enterprise | Not in this edition |
Dos límites más que conviene enunciar con claridad:
- Incrustar no es validar. El motor transporta los bytes que usted le da. Si el XML incrustado es una carga útil de factura conforme es una cuestión separada, que responde un validador; consulte la página de facturación.
- Un adjunto con tipo no es por sí solo un archivo de archivado conforme. Hacer del archivo híbrido un documento legal PDF/A-3 requiere el modo de archivado y una comprobación de conformidad independiente; consulte la página de archivado.
Documentos relacionados
Sección titulada «Documentos relacionados»- Facturas y facturación electrónica: el
caso de uso que este mecanismo hace posible: un PDF híbrido que transporta una
factura legible por máquina como su archivo asociado
Data. - Archivado y PDF/A: por qué el portador es un archivo PDF/A-3 y qué promete y qué no promete la conformidad.
- La anatomía de un archivo PDF: dónde se sitúan el árbol de nombres y el catálogo del documento en la estructura del archivo.
- Flujos y filtros: cómo se almacenan y comprimen dentro de un objeto de flujo los bytes de un archivo incrustado.
Glosario
Sección titulada «Glosario»- Flujo de archivo incrustado: un objeto de flujo PDF que contiene los bytes de un archivo externo, con un diccionario de parámetros que registra su tamaño original, fechas y una suma de comprobación (ISO 32000-2 §7.11.4).
- Árbol de nombres EmbeddedFiles: el mapa ordenado en el catálogo del documento que lista los archivos incrustados por nombre, de modo que un lector pueda enumerar los adjuntos sin escanear todo el documento.
- Archivo asociado: un archivo incrustado vinculado a una parte del documento
por una asociación
/AF(en el catálogo del documento, una página o un objeto) y que lleva unaAFRelationshipque enuncia cómo se relaciona con ese contenido; el caso a nivel de documento —la especificación de archivo en el arreglo/AFdel catálogo— es el que centra esta página (ISO 32000-2 §14.13.3). - AFRelationship: la clave de especificación de archivo cuyo valor nombra la
relación (ISO 32000-2 §7.11.3). Toma uno de ocho valores estándar (
Source,Data,Alternative,Supplement,EncryptedPayload,FormData,Schema,Unspecified) o un valor personalizado;Dataes el valor que usa la carga útil de una factura electrónica híbrida. - PDF/A-3: el perfil de archivado ISO 19005-3 que permite incrustar archivos de cualquier formato, habilitando un documento híbrido conforme.
- Factura híbrida: un único archivo PDF que es a la vez una página legible por humanos y una carga útil de factura incrustada legible por máquina.