A PDF is a container, not a sheet of paper
PDFs can carry whole files inside them, in a name tree the page never shows. How embedded files work, why PDF/A-3 exists, and the bug that loses old attachments.
Most people picture a PDF as a stack of printed pages that happens to live on a computer. It’s a reasonable mental model and it’s wrong in a way that matters. A PDF is a container. The pages are one of the things it holds, alongside fonts, colour profiles, metadata, form definitions, bookmarks and, if you want, entire other files of any type at all.
That last one is the least known and the most useful. A spreadsheet, an XML document, a folder’s worth of raw measurements: all of it can live inside the PDF, travel with it, and be pulled back out by any reader. files.co does it in the browser with attach files to a PDF, and it’s worth understanding what actually happens to the file when you do.
Where an attachment lives
Every PDF has a catalog, the root object that says where everything else is. Hanging off it there can be a name tree, and inside that a branch called /EmbeddedFiles. That branch maps names to file specifications, and each file specification points at a stream holding the actual bytes of your attachment, compressed.
A name tree is not a flat list. The specification lets it be a proper tree: a root node with /Kids pointing at intermediate nodes, each covering an alphabetical slice of the names, so that a reader can find one entry among thousands without walking the lot. Small documents usually get a single node with a flat /Names array. Big ones, or ones produced by systems that expect to hold a lot of attachments, get the branching version.
This is the whole reason attachments show up in a reader’s paperclip panel rather than on a page. They’re referenced from the document’s structure, not from the page content. Nothing is drawn, nothing shifts, the layout is untouched. Someone who never opens the panel will never know they’re there.
The bug that quietly loses your old attachments
Here’s where the tree structure stops being trivia. Add an attachment to a PDF that already had some, and a library that just appends can create a /Names array right next to the existing /Kids. A node with both keys is invalid. Readers handle invalid nodes however they feel like, and a common outcome is that the panel shows only the attachments you just added while the earlier ones vanish from view. The bytes are still in the file. Nobody can reach them.
That’s a nasty failure because it looks like success. You attached a file, the file is there, you shipped the document. The three attachments the previous person put in are gone from every panel that opens it.
The engine behind our tool flattens the tree into a single sorted /Names array before attaching, so the new entries land in the same array as the old ones, and sorts it again afterwards, because the specification asks for entries in key order and appending doesn’t keep them that way. It’s an unglamorous fix for a problem you’d only discover months later.
PDF/A-3 and the hybrid invoice
Attachments are also why one archival standard exists at all. As covered in PDF/A, explained, PDF/A-2 tightened PDF into something predictable enough to archive for decades. PDF/A-3 is nearly the same standard with one deliberate loosening: it allows arbitrary files of any type to be embedded alongside the archived pages.
That single change is what hybrid electronic invoicing is built on. A Factur-X or ZUGFeRD invoice is one file that is simultaneously a human-readable page and a machine-readable XML document, because the XML rides inside the PDF/A-3. No pairing, no matching filenames, no risk of the two halves disagreeing after someone edits one of them.
The standard also has a field for saying why a file is attached: whether it’s the source the document was generated from, supplementary data, an alternative representation, and so on. Our tool writes it as unspecified by default rather than guessing, because claiming a spreadsheet is the authoritative source of a document when we have no idea is worse than admitting we don’t know. If you need conformance for a specific archival profile, convert to PDF/A is a separate step with its own rules.
Compression is not encryption
The embedded stream is compressed with Flate. That is a size optimisation and nothing else. An attachment inside a PDF is not encrypted, and anyone holding the file can extract it in a couple of clicks.
Say it out loud because the container metaphor invites the opposite intuition: things “inside” something feel protected. They aren’t. Treat an attachment exactly like an email attachment, because in terms of who can read it, that’s what it is. If you’re in the habit of doing a final pass before a document goes out, attachments belong on that checklist next to metadata; what to check before sending a PDF covers the rest of it.
What you actually get
Before anything is modified, the tool lists what the document already carries, with names and real sizes, and lets you save those out. Existing attachments are always preserved. A new file whose name collides with an old one gets numbered rather than overwriting anything.
The practical ceiling is twenty files and 50 MB per pass, lower on an iPhone where the browser hands a page much less memory. Expect the document to grow by roughly the compressed size of what you put in, which for CSV or XML is very little and for a JPEG or a zip is close to the full size, since those are already squeezed.
One refusal worth knowing: a password-protected PDF is rejected instead of being rewritten half-blind. And support varies at the far end. Desktop readers handle attachments well, mobile ones often don’t show a panel at all, so if the recipient is on a phone, tell them what’s inside rather than assuming they’ll spot the paperclip.