Attachments
A PDF can carry arbitrary files inside it. Source spreadsheets alongside a report, the XML a rendered invoice came from, an image referenced in a form: the file travels with the document and is offered to the reader in a viewer’s attachments panel.
UniPDF has two ways to attach a file, and the choice determines where the attachment shows up.
| Approach | Where it lives | How the reader sees it |
|---|---|---|
pdfWriter.AttachFile(file) | The document’s /Names /EmbeddedFiles tree. | In the viewer’s attachments panel. Not tied to any page. |
annotator.CreateFileAttachmentAnnotation(def) | A file attachment annotation on a page. | A clickable pin or paperclip icon at a position on the page, and usually in the panel too. |
Both build the same model.EmbeddedFile, so the file itself is described identically
either way. Only the placement differs. Use the document-level form for supporting
material that belongs to the document as a whole; use the annotation form when the
attachment relates to a specific spot on a specific page. The annotation route is
covered in the file attachment annotation guide.
The EmbeddedFile
emFile, err := model.NewEmbeddedFile("dummy.xml")
if err != nil {
return err
}
emFile.Name = "invoice-source.xml"
emFile.Description = "Source XML for the rendered invoice"
emFile.Relationship = model.RelationshipDataNewEmbeddedFile reads the file, sniffs its MIME type, and computes an MD5 checksum.
NewEmbeddedFileFromContent does the same from a byte slice you already have.
Name is the display name and the key the file gets in the name tree, so it needs to
be unique within the document. NewEmbeddedFile defaults it to the base name of the
path, which means attaching the same file more than once requires overwriting it.
NewEmbeddedFileFromContent defaults it to the literal string attachment.
Relationship records why the file is there, and maps onto the PDF AFRelationship
values: RelationshipSource, RelationshipData, RelationshipAlternative,
RelationshipSupplement and RelationshipUnspecified. It’s metadata, and the zero
value is RelationshipSource, so a struct you never set writes Source.
Content is always Flate compressed on the way in. CreationTime and ModTime
default to now when left zero.
Where to look
| Guide | Covers |
|---|---|
| Attaching a file | AttachFile, the two EmbeddedFile constructors, and which fields actually reach the output. |
| Retrieving attached files | GetAttachedFiles, and what the returned metadata does and does not round-trip. |