Embedded File Streams

Introduction

Embedded file streams allow you to embed an external file directly within the body of a PDF file. This embedded file streams are referenced by a file specification then, which can be attached to the global embedded files name tree or a file attachment annotation.

The EmbeddedFileStream Class

An embedded file stream is represented by the SetaPDF_Core_EmbeddedFileStream class which offers following getter and setter methods:

create()

Create an embedded file stream.

getMimeType()

Get the subtype of the embedded file.

getParams()

Get the entries and data of the embedded file parameter dictionary.

setMimeType()

Set the mime type (or subtype) of the embedded file stream.

setParams()

Set the entries in the embedded file parameter dictionary.

The FileSpecification Class

An embedded file stream is referenced by a file specification through its EF (embedded file stream) entry. A file specification offers several other methods:

createEmbedded()

Create a file specification with an embedded file stream.

getCollectionItem()

Get the collection item data.

getDescription()

Get the descriptive text associated with the file specification.

getDictionary()

Get the dictionary.

getEmbeddedFileStream()

Get the embedded file stream object.

getFileSpecification()

Get the file specification value.

getFileSystem()

Get name of the file system.

getUnicodeFileSpecification()

Get the unicode text file specification value.

getVolatile()

Get the volatile flag.

setCollectionItem()

Set the collection item data.

setDescription()

Set the descriptive text associated with the file specification.

setEmbeddedFileStream()

Set the embedded file stream object.

setFileSpecification()

Set the file specification value.

setFileSystem()

Set the file system name.

setUnicodeFileSpecification()

Set the unicode text file specification value.

setVolatile()

Set the volatile flag.

To create a file specification with an embedded file stream you should use the static helper method createEmbedded().

The EmbeddedFiles Name Tree

The EmbeddedFiles name tree maps name strings to file specifications for embedded file streams. It is represented by the SetaPDF_Core_Document_Catalog_Names_EmbeddedFiles which can be resolved by following code:

PHP
$document = new \SetaPDF_Core_Document();
//...
$embeddedFiles = $document->getCatalog()->getNames()->getEmbeddedFiles();

add()

Adds an embedded file by its file specification.

get()

Get an embedded file by its name.

getAll()

Get all embedded files.

remove()

Remove an embedded file.

The registered names should be PDF strings (PDFDoc encoding or UTF-16BE including BOM).
Keep in mind that name parameter are encoding specific.

Examples

Add Attachments / Embedded Files

PHP
<?php
require_once('library/SetaPDF/Autoload.php');

$writer = new \SetaPDF_Core_Writer_Http('embedded-files.pdf', true);
$document = new \SetaPDF_Core_Document($writer);

// let's create a page
$document->getCatalog()->getPages()->create(\SetaPDF_Core_PageFormats::A4);

// get the embedded files name tree
$embeddedFiles = $document->getCatalog()->getNames()->getEmbeddedFiles();

// create an embedded file specification from a file in the file system
$fs = \SetaPDF_Core_FileSpecification::createEmbedded(
    $document, 'files/pdfs/tektown/Logo.pdf', 'Logo.pdf'
);
$embeddedFiles->add(\SetaPDF_Core_Encoding::toPdfString('Logo.pdf'), $fs);

// embedded a dynamically created text file
$textFile = 'A simple text content';
$fs = \SetaPDF_Core_FileSpecification::createEmbedded(
    $document, new \SetaPDF_Core_Reader_String($textFile), 'text-file.txt', [
        \SetaPDF_Core_EmbeddedFileStream::PARAM_CHECK_SUM => md5($textFile, true),
        \SetaPDF_Core_EmbeddedFileStream::PARAM_MODIFICATION_DATE => new DateTime(
            '2017-02-28 10:36:00'
        )
    ],
    'text/plain'
);
$fs->setDescription('The description of this embedded file.');

$embeddedFiles->add(\SetaPDF_Core_Encoding::toPdfString('text-file.txt'), $fs);

// show the attachments panel
$document->getCatalog()->setPageMode(\SetaPDF_Core_Document_PageMode::USE_ATTACHMENTS);
$document->save()->finish();

Get Attachments / Embedded Files

PHP
<?php
require_once('library/SetaPDF/Autoload.php');

// create a document
$document = \SetaPDF_Core_Document::loadByFilename('files/pdfs/tektown/products/All-Portfolio.pdf');

// get names
$names = $document->getCatalog()->getNames();
// get the "embedded files" name tree
$embeddedFiles = $names->getEmbeddedFiles();

// extract the file
if (isset($_GET['f'])) {
    $file = $embeddedFiles->get($_GET['f']);
    if ($file instanceof \SetaPDF_Core_FileSpecification) {
        // resolve the filename
        $filename = $file->getFileSpecification();
        // resolve the file stream
        $embeddedFileStream = $file->getEmbeddedFileStream();

        // get the content type
        $contentType = $embeddedFileStream->getMimeType();
        // or set a default content type
        if ($contentType === null) {
            $contentType = 'application/force-download';
        }

        // pass the file to the client
        $stream = $embeddedFileStream->getStream();
        header('Content-Type: ' . $contentType);
        header('Content-Disposition: attachment; filename="' . $filename . '";');
        header('Content-Transfer-Encoding: binary');
        header('Content-Length: ' . strlen($stream));
        echo $stream;
        die();
    }
}

$files = $embeddedFiles->getAll();

foreach ($files AS $name => $file) {
    $filename = $file->getFileSpecification();
    echo '<a href="?f=' . urlencode($name) . '">' . htmlspecialchars($filename) . '</a><br />';
}