コンテンツにスキップ
getnextpdf.com

PDF はコンテナである — 埋め込みファイルと関連データ

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

ほとんどの人は、PDF をページの束として思い浮かべます。それは目に見える部分です。しかし PDF はコンテナでもあり、内部に他のまるごとのファイル — スプレッドシート、XML ペイロード、元のソース文書 — を携えることができ、それらを誰かに手渡す同じ 1 つのファイルにまとめられます。

このページは、それがどう働くかを説明します。バイトを格納する埋め込みファイルストリーム、それらを列挙する名前ツリー、そして添付がただそこにあるだけか、それとも実際に何かを意味するかを決める 1 つのキーです。

型のない 添付と 型のある 添付は、人間には同一に見えます。どちらも PDF の内側に乗ったファイルであり、このエンジンでは、どちらも文書に関連付けられています。違いは、一方が機械にそれが何のためのものかを告げ、もう一方は機械が推測すべき関係を空白のまま残すことです。

その違いこそが、ハイブリッド電子インボイスにとってのすべてです。税務プラットフォームはあなたのインボイスページを読みません。あなたが埋め込んだ XML を読みます。もしその XML が、可視文書のためのインボイス データ としてではなく、未分化のブロブとして添付されていれば、準拠したリーダーはそれが処理すべきペイロードだと確実に知る術を持ちません。ページは完璧に見えます。インボイスは却下されます。失敗は数日後に、保留された支払いを伴って届きます。

ファイルを生成するレイヤーで関係を正しく設定することは、却下されたインボイスを 1 件ずつ発見していくよりも、はるかに安上がりです。

  • PDF は 任意のファイルのバイトを埋め込む ことができます。埋め込みファイルストリーム として、です(Spec: ISO 32000-2, §7.11.4)。ストリームは、データに加えて小さなパラメータディクショナリ — 元のサイズ、日付、チェックサム — を携えます。
  • 埋め込みファイルは EmbeddedFiles 名前ツリー にカタログ化されます。だからリーダーは、文書全体を走査せずに名前で列挙できます。
  • 関連ファイル はもう一歩進みます。それは AFRelationshipSpec: ISO 32000-2, §7.11.3)を宣言します — 8 つの標準値(SourceDataAlternativeSupplementEncryptedPayloadFormDataSchemaUnspecified)のいずれか、あるいはカスタム値 — そのファイルが添付先のコンテンツに どう 関係するかを告げます。
  • その型付けされた関係こそが、ハイブリッド電子インボイス(ZUGFeRD / Factur-X)と PDF/A-3 添付(Spec: ISO 19005-3, PDF/A-3)の背後にある機構です。
  • NextPDF は、生のコンテナプリミティブをコアでサポートします。明示的な関係を伴う embedFile()embedFileFromString() です。Advanced エディションは、これらのプリミティブの上に、専用の EN 16931 / ZUGFeRD / Factur-X 電子インボイス埋め込み器を 追加します

これを、互いに積み重なった 2 つのレイヤーとして考えてください。

下位レイヤー はストレージです。埋め込みファイルストリーム(Spec: ISO 32000-2, §7.11.4)は、元のファイルのバイトを PDF ストリームオブジェクトで包んだもので、パラメータディクショナリが元のサイズ、変更日、そして非圧縮データのチェックサムを記録します。ストリームには ファイル仕様 ディクショナリ経由で到達し、その /EF ディクショナリが埋め込みファイルストリームを指します — ストリーム自体が /EF を携えるのではありません。リーダーはファイルをバイト単位でそっくり取り出せます。これらのファイルを発見可能にするため、文書カタログは EmbeddedFiles 名前ツリー — 名前から各ファイル仕様へのソート済みマップ — を保持します。だからビューアは、すべてのページを歩かずに「この PDF の内側にはこれら 3 つのファイルがあります」と列挙できます。

上位レイヤー は意味です。それ自体では、埋め込みファイルはただ存在するだけです。関連ファイル機構(Spec: ISO 32000-2, §14.13)は、ファイルを何か — 文書全体、ページ、グラフィックスオブジェクト — に結びつけ、AFRelationship のスタンプを押します。ISO 32000-2 は 8 つの標準値からなる小さな語彙を定義し(Spec: ISO 32000-2, §7.11.3)、カスタム値も許します。各標準値は、正確な問いに答えます。

AFRelationshipファイルについて何を主張するか
Source可視コンテンツがそこ から 生成された元の素材(たとえば元のワープロ文書)。
Data可視コンテンツに結びついた構造化データ — 典型例は、レンダリングされたインボイスページの背後にあるインボイス XML。
Alternative同じコンテンツの代替表現(たとえば音声版や動画版)。
Supplementコンテンツを拡張するが、その一部ではない補足素材。
EncryptedPayload埋め込みファイルは、PDF が不透明なブロブとして包む暗号化ペイロード。
FormDataファイルはフォームデータ(FDF、XFDF、または XML フォームペイロード)。
Schemaファイルは Data ファイルの構造を記述するスキーマ(たとえば XML データの XSD、または JSON Schema)。
Unspecified関係は意図的に明示されていない。正直だが、機械には何も告げない。

これら 8 つを超えて、標準はアプリケーション固有のカスタム関係値も許します。だから語彙は固定ではなく拡張可能です。

関連ファイルは、1 つのキー単独ではなく、協働する 2 つのものによって定義されます。/AF 関連付けはファイル仕様を文書の一部に 結びつけ、ファイル仕様内の AFRelationship キーがそのうえで 意味的な関係を述べます。関連付けポイント(文書カタログ、ページ、またはオブジェクト)上の /AF エントリは 配列 です — その配列は 1 つ以上のファイル仕様ディクショナリを、通常は間接参照として含みます。/AF は単一の参照ではありません。文書レベルの関連ファイルとは、文書カタログの /AF 配列に挙げられたファイル仕様であり、自身の AFRelationship を携えます。そのスプレッドシートを Unspecified とマークすれば、文書に関連付けはしたが、機械には なぜ かについて何も告げていないことになります。同じスプレッドシートを Data とマークすれば、すべての準拠したリーダーに、それが何で何のためのものかを告げたことになります。バイトは同じです。意味は同じではありません。

これが、電子インボイスのケースが「XML ファイルを添付する」ではない理由です。それは「この XML を、準拠した PDF/A-3 キャリアの内側で、この文書のための Data 関連ファイルとして埋め込む」です — インボイスの有効性と法的受容は、キャリアが行わない別個のチェックのままです。フローには 4 つの段階があり、その順序こそが正しさを保ちます。

  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.

その第 4 段階こそが、PDF/A-3 が独立したプロファイルとして存在する理由です。以前のアーカイブプロファイルは、何を埋め込めるかを制限していました。PDF/A-3(Spec: ISO 19005-3, PDF/A-3)は、任意 の形式のファイルを準拠したアーカイブ文書の内側に乗せることを許す部分です。それは埋め込みペイロードを許します — そのペイロードを検証したり、法的地位を付与したりはしません。それがなければ、ハイブリッドインボイス — 人が読むページであると同時に税務システムがパースするデータでもある 1 つのファイル — は、準拠したアーカイブ PDF/A 文書には一切なれません。インボイスが 有効 で法的に 受容される かどうかは、別個の問いのままです。Advanced エディションが追加する 専用の電子インボイス埋め込み器は、まさにこの上の利便性の継ぎ目です。ペイロードを埋め込み、関係を Data に設定し、正しく登録するので、あなたがコンテナの配管を手で組み立てる必要はありません。より深いインボイスとアーカイブの仕組みは、下にリンクした 2 つの隣接ページにあります。このページは、その両方が立つコンテナについてのものです。

小さく完全なプログラムです。重要な 2 つの呼び出しは、型のない 関連ファイルと 型のある 関連ファイルの差そのものであり、関係はあなたが設定すべき明示的な引数です。このエンジンでは、両方 の呼び出しが関連ファイルを生成します。embedFile()embedFileFromString() は常に文書カタログの /AF 配列にファイル仕様を登録するので、関係が変えるのは 関連付けが何を意味するか だけです。それはデフォルトで Unspecified になり、ファイルを関連付けはするが機械にはなぜかについて何も告げません。電子インボイスのペイロードでは、リーダーが見つけられるよう Data に設定します。

<?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();

'/Data' の関係は紛れもありません。Unspecified のまま残された最初の添付も同じく関連付けられています。ただ、述べられた意味がないだけです。どちらの呼び出しについても、エンジンは埋め込みファイルストリームを書き、ファイルを EmbeddedFiles 名前ツリーに加え、そのファイル仕様を文書カタログの /AF 配列に挙げ、あなたが述べた関係を記録します — エンジンがあなたの代わりに選ぶことはありません。このエンジンには名前ツリーのみのモードはありません。この方法で埋め込むすべてのファイルは文書に関連付けられたファイルなので、関係があなたの制御する唯一のレバーです。

よくある思い込みは、「埋め込み」と「関連付け」が同じものを指す 2 つの言葉だというものです。それらは違います。埋め込み はストレージの話です — バイトが PDF の内側にあること。関連付け は結びつきの話です — ファイル仕様が文書の一部の /AF 配列に挙げられ、それが AFRelationship を携えること。抽象的な PDF モデルでは、ファイルは一度も関連付けられることなく名前ツリーに埋め込まれることがあり得ます。NextPDF の embedFile() の経路はそこに放置しません — 常に /AF 関連付けを書きます — だからこのエンジンでは、開かれた問いは決してファイルが関連付けられている かどうか ではなく、関係が何を述べるか です。

第 2 の罠は、どの添付がインボイスかをビューアが「見抜いてくれる」と想定することです。準拠したリーダーは推測しないことになっています。リーダーは、関係が Data だと述べているファイルを探します。関係を Unspecified のまま残せば、ペイロードを関連付けはしたが、その役割について機械に有用なことを何も告げていないことになります。

コンテナ機構は、正直に語る価値のある形で強力です。embedFile() は、PHP プロセスが読めるどんなパスでも読みます。それは機能であり — そして同時に境界でもあります。エンジンは与えられたバイトを添付します。あるパスが、あなたが 公開を意図した ものかどうかを、エンジンが代わりに決めることはなく、できもしません。

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

率直に述べる価値のある 2 つのさらなる限界があります。

  • 埋め込みは検証ではありません。 エンジンはあなたが与えたバイトを運びます。埋め込まれた XML が 準拠した インボイスペイロードかどうかは別個の問いで、バリデータが答えます — インボイスのページを参照してください。
  • 型のある添付は、それ単独では準拠したアーカイブファイルではありません。 ハイブリッドファイルを正規の PDF/A-3 文書にするには、アーカイブモードと独立した適合性チェックが必要です — アーカイブのページを参照してください。
  • Invoices and e-invoicing — この機構が可能にするユースケース。機械可読なインボイスをその Data 関連ファイルとして携えるハイブリッド PDF。
  • Archival and PDF/A — なぜキャリアが PDF/A-3 ファイルなのか、そして適合性が何を約束し、何を約束しないか。
  • The anatomy of a PDF file — 名前ツリーと文書カタログが、ファイル構造のどこに位置するか。
  • Streams and filters — 埋め込みファイルのバイトが、ストリームオブジェクトの内側でどう格納され、圧縮されるか。
  • 埋め込みファイルストリーム(Embedded file stream) — 外部ファイルのバイトを保持する PDF ストリームオブジェクト。パラメータディクショナリが元のサイズ、日付、チェックサムを記録する(ISO 32000-2 §7.11.4)。
  • EmbeddedFiles 名前ツリー(EmbeddedFiles name tree) — 文書カタログ内のソート済みマップで、埋め込みファイルを名前で列挙する。だからリーダーは文書全体を走査せずに添付を列挙できる。
  • 関連ファイル(Associated file)/AF 関連付け(文書カタログ、ページ、またはオブジェクト上)によって文書の一部に結びつけられた埋め込みファイルで、それがそのコンテンツにどう関係するかを述べる AFRelationship を携える。文書レベルのケース — カタログの /AF 配列内のファイル仕様 — が、このページの中心とするものである(ISO 32000-2 §14.13.3)。
  • AFRelationship — その値が関係を名付けるファイル仕様キー(ISO 32000-2 §7.11.3)。8 つの標準値(SourceDataAlternativeSupplementEncryptedPayloadFormDataSchemaUnspecified)のいずれか、またはカスタム値をとる。Data は、ハイブリッド電子インボイスのペイロードが使う値。
  • PDF/A-3 — 任意の形式のファイルの埋め込みを許し、準拠したハイブリッド文書を可能にする ISO 19005-3 のアーカイブプロファイル。
  • ハイブリッドインボイス(Hybrid invoice) — 人間可読なページであると同時に、機械可読な埋め込みインボイスペイロードでもある 1 つの PDF ファイル。