PDF jest kontenerem: pliki osadzone i dane powiązane
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
W skrócie
Dział zatytułowany „W skrócie”Większość ludzi wyobraża sobie PDF jako stos stron. To część, którą widzisz. Ale PDF jest też kontenerem i może nosić w sobie całe inne pliki — arkusz kalkulacyjny, ładunek XML, oryginalny dokument źródłowy — zapakowane w ten sam pojedynczy plik, który wręczasz komuś innemu.
Ta strona wyjaśnia, jak to działa: strumień pliku osadzonego, który przechowuje bajty, drzewo nazw, które je wymienia, oraz jeden klucz, który decyduje o tym, czy załącznik po prostu tam siedzi, czy faktycznie coś znaczy.
Dlaczego to ma znaczenie
Dział zatytułowany „Dlaczego to ma znaczenie”Nieotypowany załącznik i otypowany wyglądają dla człowieka identycznie. Oba to plik jadący wewnątrz PDF i — w tym silniku — oba są powiązane z dokumentem. Różnica polega na tym, że jeden z nich mówi maszynie, do czego służy, a drugi pozostawia relację pustą, by maszyna zgadywała.
Ta różnica to cała gra dla hybrydowej e-faktury. Platforma podatkowa nie czyta strony twojej faktury; czyta XML, który osadziłeś. Jeśli ten XML jest dołączony jako nieokreślony bloob, a nie jako dane faktury dla widocznego dokumentu, zgodny czytnik nie ma wiarygodnego sposobu, by wiedzieć, że to ładunek do przetworzenia. Strona wygląda idealnie. Faktura zostaje odrzucona. Niepowodzenie przychodzi po kilku dniach, a za nim wstrzymana płatność.
Ustawienie właściwej relacji w warstwie, która wytwarza plik, jest znacznie tańsze niż odkrywanie tego po jednej odrzuconej fakturze na raz.
Wersja skrócona
Dział zatytułowany „Wersja skrócona”- PDF może osadzić bajty dowolnego pliku jako strumień pliku osadzonego (Spec: ISO 32000-2, §7.11.4ISO 32000-2 §7.11.4). Strumień niesie dane plus niewielki słownik parametrów: oryginalny rozmiar, daty oraz sumę kontrolną.
- Pliki osadzone są skatalogowane w drzewie nazw
EmbeddedFiles, dzięki czemu czytnik może je wyliczyć po nazwie bez przeglądania całego dokumentu. - Plik powiązany idzie o krok dalej: deklaruje
AFRelationship(Spec: ISO 32000-2, §7.11.3ISO 32000-2 §7.11.3) — jedną z ośmiu standardowych wartości (Source,Data,Alternative,Supplement,EncryptedPayload,FormData,Schema,Unspecified) lub wartość niestandardową — mówiąc, jak plik odnosi się do treści, do której jest dołączony. - Ta otypowana relacja to mechanizm stojący za hybrydowymi e-fakturami (ZUGFeRD / Factur-X) oraz załącznikami PDF/A-3 (Spec: ISO 19005-3, PDF/A-3ISO 19005-3 PDF/A-3).
- NextPDF wspiera surowe prymitywy kontenera w edycji podstawowej:
embedFile()orazembedFileFromString()z jawną relacją. Edycje zaawansowane dodają na bazie tych prymitywów dedykowany osadzacz e-faktur EN 16931 / ZUGFeRD / Factur-X.
Jak podchodzi do tego NextPDF
Dział zatytułowany „Jak podchodzi do tego NextPDF”Pomyśl o tym jak o dwóch warstwach ułożonych jedna na drugiej.
Niższa warstwa to przechowywanie. Strumień pliku osadzonego
(Spec: ISO 32000-2, §7.11.4ISO 32000-2 §7.11.4) to bajty oryginalnego pliku
opakowane w obiekt strumienia PDF, ze słownikiem parametrów zapisującym
oryginalny rozmiar, datę modyfikacji oraz sumę kontrolną nieskompresowanych
danych. Do strumienia dociera się przez słownik specyfikacji pliku, którego
słownik /EF wskazuje na strumień pliku osadzonego — sam strumień nie niesie
/EF. Czytnik może wyciągnąć plik z powrotem bajt po bajcie. Aby te pliki dało
się odnaleźć, katalog dokumentu trzyma drzewo nazw EmbeddedFiles — posortowaną
mapę od nazwy do każdej specyfikacji pliku — dzięki czemu czytnik może wymienić
„oto 3 pliki wewnątrz tego PDF” bez przechodzenia przez każdą stronę.
Wyższa warstwa to znaczenie. Sam z siebie plik osadzony jest po prostu
obecny. Mechanizm plików powiązanych (Spec: ISO 32000-2, §14.13ISO 32000-2 §14.13)
dołącza plik do czegoś — całego dokumentu, strony, obiektu graficznego — i
stempluje go za pomocą AFRelationship. ISO 32000-2 definiuje niewielki
słownik ośmiu standardowych wartości (Spec: ISO 32000-2, §7.11.3ISO 32000-2 §7.11.3)
i dopuszcza też wartości niestandardowe; każda standardowa wartość odpowiada na
precyzyjne pytanie:
AFRelationship | Co stwierdza o pliku |
|---|---|
Source | To materiał źródłowy, z którego wygenerowano widoczną treść (na przykład oryginalny dokument edytora tekstu). |
Data | To ustrukturyzowane dane powiązane z widoczną treścią — kanonicznym przypadkiem jest XML faktury stojący za wyrenderowaną stroną faktury. |
Alternative | To alternatywna reprezentacja tej samej treści (na przykład wersja audio lub wideo). |
Supplement | To materiał uzupełniający, który rozszerza treść, ale nie jest jej częścią. |
EncryptedPayload | Plik osadzony to zaszyfrowany ładunek, który PDF opakowuje jako nieprzejrzysty bloob. |
FormData | Plik to dane formularza (FDF, XFDF lub ładunek formularza XML). |
Schema | Plik to schemat opisujący strukturę pliku Data (na przykład XSD dla danych XML albo JSON Schema). |
Unspecified | Relacja jest celowo nieokreślona. Uczciwie, ale nie mówi maszynie niczego. |
Poza tymi ośmioma standard dopuszcza również niestandardowe wartości relacji charakterystyczne dla aplikacji, więc słownik jest rozszerzalny, a nie zamknięty.
Plik powiązany jest zdefiniowany przez dwie rzeczy działające razem, a nie przez
sam jeden klucz. Powiązanie /AF wiąże specyfikację pliku z częścią
dokumentu; klucz AFRelationship w specyfikacji pliku następnie stwierdza
relację semantyczną. Wpis /AF w punkcie powiązania (katalog dokumentu, strona
lub obiekt) to tablica — ta tablica zawiera jedną lub więcej słowników
specyfikacji pliku, zwykle jako odwołania pośrednie; /AF nie jest pojedynczym
odwołaniem. Plik powiązany na poziomie dokumentu to specyfikacja pliku
wymieniona w tablicy /AF katalogu dokumentu, niosąca swój AFRelationship.
Oznacz ten arkusz jako Unspecified, a powiążesz go z dokumentem, ale nie
powiesz maszynie niczego o tym, dlaczego. Oznacz ten sam arkusz jako Data, a
powiesz każdemu zgodnemu czytnikowi, czym jest i do czego służy. Bajty są takie
same. Semantyka nie.
Dlatego przypadek e-faktury nie sprowadza się do „dołącz plik XML”. Brzmi on
„osadź ten XML jako plik powiązany Data dla tego dokumentu, wewnątrz zgodnego
nośnika PDF/A-3” — przy czym ważność faktury i jej akceptacja prawna pozostają
osobnymi kontrolami, których nośnik nie wykonuje. Przepływ ma cztery etapy, a
kolejność jest tym, co utrzymuje go w poprawności.
- 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).
Ten czwarty etap to powód, dla którego PDF/A-3 istnieje jako odrębny profil.
Wcześniejsze profile archiwalne ograniczały to, co można było osadzić; PDF/A-3
(Spec: ISO 19005-3, PDF/A-3ISO 19005-3 PDF/A-3) to ta część, która pozwala,
by pliki dowolnego formatu jechały wewnątrz zgodnego dokumentu archiwalnego.
Pozwala na osadzony ładunek — nie waliduje tego ładunku ani nie nadaje statusu
prawnego. Bez niego faktura hybrydowa — jeden plik będący jednocześnie stroną,
którą czyta człowiek, i danymi, które parsuje system podatkowy — w ogóle nie
mogłaby być zgodnym dokumentem archiwalnym PDF/A; to, czy faktura jest ważna i
prawnie akceptowana, pozostaje osobnym pytaniem. Dedykowany osadzacz e-faktur,
który dodają edycje zaawansowane, to wygodny szew nad dokładnie tym: osadza
ładunek, ustawia relację na Data i poprawnie go rejestruje, dzięki czemu nie
składasz instalacji kontenera ręcznie. Głębsze mechanizmy fakturowania i
archiwizacji żyją na dwóch sąsiednich stronach, do których linki są poniżej; ta
strona dotyczy kontenera, na którym obie się opierają.
Praktyczny przykład
Dział zatytułowany „Praktyczny przykład”Mały, kompletny program. Dwa wywołania, które mają znaczenie, to różnica między
nieotypowanym plikiem powiązanym a otypowanym — a relacja to jawny argument,
który powinieneś ustawić. W tym silniku oba wywołania wytwarzają plik
powiązany: embedFile() oraz embedFileFromString() zawsze rejestrują
specyfikację pliku w tablicy /AF katalogu dokumentu, więc jedyną rzeczą, którą
zmienia relacja, jest to, co oznacza powiązanie. Domyślnie przyjmuje wartość
Unspecified, która powiązuje plik, ale nie mówi maszynie niczego o tym,
dlaczego; dla ładunku e-faktury ustawiasz ją na Data, aby czytnik mógł go
odnaleźć.
<?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();Relacja '/Data' jest niewątpliwa. Pierwszy załącznik — pozostawiony jako
Unspecified — jest powiązany tak samo, tylko bez stwierdzonego znaczenia. Dla
obu wywołań silnik zapisuje strumień pliku osadzonego, dodaje plik do drzewa
nazw EmbeddedFiles, wymienia jego specyfikację pliku w tablicy /AF katalogu
dokumentu i zapisuje relację, którą stwierdziłeś — nie wybiera jej za ciebie. Ten
silnik nie ma trybu z samym drzewem nazw: każdy plik, który osadzasz w ten
sposób, jest plikiem powiązanym z dokumentem, więc relacja to jedyna dźwignia,
którą kontrolujesz.
Częste nieporozumienie
Dział zatytułowany „Częste nieporozumienie”Częste założenie jest takie, że „osadzony” i „powiązany” to dwa słowa na to samo.
Nie są. Osadzony dotyczy przechowywania — bajty są wewnątrz PDF. Powiązany
dotyczy wiązania — specyfikacja pliku jest wymieniona w tablicy /AF w jakiejś
części dokumentu i niesie AFRelationship. W abstrakcyjnym modelu PDF plik może
być osadzony w drzewie nazw, nigdy nie będąc powiązanym; ścieżka embedFile()
NextPDF nie pozostawia go w tym stanie — zawsze zapisuje powiązanie /AF — więc
dla tego silnika otwartym pytaniem nigdy nie jest czy plik jest powiązany, lecz
co mówi relacja.
Druga pułapka: założenie, że czytnik „domyśli się”, który załącznik jest fakturą.
Zgodny czytnik nie powinien zgadywać. Szuka pliku, którego relacja mówi Data.
Pozostaw relację jako Unspecified, a powiążesz ładunek, mówiąc maszynie nic
użytecznego o jego roli.
Ograniczenia i granice
Dział zatytułowany „Ograniczenia i granice”Mechanizm kontenera jest potężny w sposób, o którym warto być uczciwym:
embedFile() odczytuje dowolną ścieżkę, którą może odczytać proces PHP. To jest
funkcja — i to jest też granica. Silnik dołącza bajty, które mu dano; nie
decyduje, i nie może, za ciebie o tym, czy dana ścieżka jest tą, którą
zamierzałeś ujawnić.
| Edition | Availability |
|---|---|
| Core |
|
| Pro | Not in this edition |
| Enterprise | Not in this edition |
Dwie kolejne granice, które warto wyłożyć wprost:
- Osadzanie to nie walidacja. Silnik niesie bajty, które mu podasz. To, czy osadzony XML jest zgodnym ładunkiem faktury, to osobne pytanie, na które odpowiada walidator — zobacz stronę o fakturowaniu.
- Otypowany załącznik sam w sobie nie jest zgodnym plikiem archiwalnym. Uczynienie pliku hybrydowego prawnym dokumentem PDF/A-3 wymaga trybu archiwalnego oraz niezależnej kontroli zgodności — zobacz stronę o archiwizacji.
Powiązane dokumenty
Dział zatytułowany „Powiązane dokumenty”- Faktury i e-fakturowanie —
przypadek użycia, który ten mechanizm umożliwia: hybrydowy PDF niosący
odczytywalną maszynowo fakturę jako swój plik powiązany
Data. - Archiwizacja i PDF/A — dlaczego nośnik to plik PDF/A-3 oraz co zgodność obiecuje, a czego nie.
- Anatomia pliku PDF — gdzie w strukturze pliku znajdują się drzewo nazw i katalog dokumentu.
- Strumienie i filtry — jak bajty pliku osadzonego są przechowywane i kompresowane wewnątrz obiektu strumienia.
Słownik pojęć
Dział zatytułowany „Słownik pojęć”- Strumień pliku osadzonego — obiekt strumienia PDF przechowujący bajty zewnętrznego pliku, ze słownikiem parametrów zapisującym jego oryginalny rozmiar, daty oraz sumę kontrolną (ISO 32000-2 §7.11.4).
- Drzewo nazw EmbeddedFiles — posortowana mapa w katalogu dokumentu, która wymienia pliki osadzone po nazwie, dzięki czemu czytnik może wyliczyć załączniki bez przeglądania całego dokumentu.
- Plik powiązany — plik osadzony związany z częścią dokumentu powiązaniem
/AF(w katalogu dokumentu, na stronie lub na obiekcie) i niosącyAFRelationship, który stwierdza, jak odnosi się do tej treści; przypadek na poziomie dokumentu — specyfikacja pliku w tablicy/AFkatalogu — to ten, na którym skupia się ta strona (ISO 32000-2 §14.13.3). - AFRelationship — klucz specyfikacji pliku, którego wartość nazywa relację
(ISO 32000-2 §7.11.3). Przyjmuje jedną z ośmiu standardowych wartości
(
Source,Data,Alternative,Supplement,EncryptedPayload,FormData,Schema,Unspecified) lub wartość niestandardową;Datato wartość, której używa ładunek hybrydowej e-faktury. - PDF/A-3 — profil archiwalny ISO 19005-3, który pozwala osadzać pliki dowolnego formatu, umożliwiając zgodny dokument hybrydowy.
- Faktura hybrydowa — jeden plik PDF, który jest jednocześnie czytelną dla człowieka stroną oraz odczytywalnym maszynowo osadzonym ładunkiem faktury.