Embed files to PDF document in C# and VB.NET

If a PDF document references an external file and the PDF document is archived or transmitted, it’s necessary to make a provision to ensure that the external references remain valid.

One way to do this is to arrange for copies of the external files to accompany the PDF document. Another and preferable way is to embed the contents of referenced files directly within the body of the PDF document. This method makes the PDF document a self-contained unit that can be stored or transmitted as a single entity.

To add attachments to your PDF files programmatically in C# and VB.NET, you can use the GemBox.Pdf component. The PdfEmbeddedFileSpecificationTree class represents them in the GemBox.Pdf library, and you can access them via the EmbeddedFiles property of the PdfDocument class.

GemBox.Pdf supports embedding files to a PDF document from either a file system or Streams, as shown in the following examples.

PDF document with files embedded using GemBox.Pdf
Screenshot of PDF document with files embedded using GemBox.Pdf

Embed files from a file system

Embedding files to a PDF document from a file system is convenient and easy.

The following example shows how to embed files in PDF documents from an extracted zip archive.

Upload your file (Drag file here)
using System.IO;
using System.IO.Compression;
using GemBox.Pdf;

class Program
{
    static void Main()
    {
        // If using the Professional version, put your serial key below.
        ComponentInfo.SetLicense("FREE-LIMITED-KEY");

        using (var document = PdfDocument.Load("%InputFileName%"))
        {
            // Make Attachments panel visible.
            document.PageMode = PdfPageMode.UseAttachments;

            // Extract all the files in the zip archive to a directory on the file system.
            ZipFile.ExtractToDirectory("%#Attachments.zip%", "Attachments");

            // Embed in the PDF document all the files extracted from the zip archive.
            foreach (var filePath in Directory.GetFiles("Attachments", "*", SearchOption.AllDirectories))
            {
                var fileSpecification = document.EmbeddedFiles.Add(filePath).Value;

                // Set embedded file description to the relative path of the file in the zip archive.
                fileSpecification.Description = filePath.Substring(filePath.IndexOf('\\') + 1).Replace('\\', '/');
            }

            // Delete the directory where zip archive files were extracted to.
            Directory.Delete("Attachments", recursive: true);

            document.Save("Embedded Files from file system.pdf");
        }
    }
}
Imports System.IO
Imports System.IO.Compression
Imports GemBox.Pdf

Module Program

    Sub Main()

        ' If using the Professional version, put your serial key below.
        ComponentInfo.SetLicense("FREE-LIMITED-KEY")

        Using document = PdfDocument.Load("%InputFileName%")

            ' Make Attachments panel visible.
            document.PageMode = PdfPageMode.UseAttachments

            ' Extract all the files in the zip archive to a directory on the file system.
            ZipFile.ExtractToDirectory("%#Attachments.zip%", "Attachments")

            ' Embed in the PDF document all the files extracted from the zip archive.
            For Each filePath In Directory.GetFiles("Attachments", "*", SearchOption.AllDirectories)

                Dim fileSpecification = document.EmbeddedFiles.Add(filePath).Value

                ' Set embedded file description to the relative path of the file in the zip archive.
                fileSpecification.Description = filePath.Substring(filePath.IndexOf("\"c) + 1).Replace("\"c, "/"c)
            Next

            ' Delete the directory where zip archive files were extracted to.
            Directory.Delete("Attachments", recursive:=True)

            document.Save("Embedded Files from file system.pdf")
        End Using
    End Sub
End Module

Embed files from Streams

If your application doesn't have access to a file system or uses some other source of embedded files such as dynamically created streams or streams embedded in an assembly, you can still embed them into a PDF document using GemBox.Pdf.

The example below shows how to embed such files to an existing PDF document from Streams of zip archive entries.

Upload your file (Drag file here)
using System.IO;
using System.IO.Compression;
using GemBox.Pdf;

class Program
{
    static void Main()
    {
        // If using the Professional version, put your serial key below.
        ComponentInfo.SetLicense("FREE-LIMITED-KEY");

        using (var document = PdfDocument.Load("%InputFileName%"))
        {
            // Make Attachments panel visible.
            document.PageMode = PdfPageMode.UseAttachments;

            // Embed in the PDF document all the files from the zip archive.
            using (var archiveStream = File.OpenRead("%#Attachments.zip%"))
            using (var archive = new ZipArchive(archiveStream, ZipArchiveMode.Read, leaveOpen: true))
                foreach (var entry in archive.Entries)
                    if (!string.IsNullOrEmpty(entry.Name))
                    {
                        var fileSpecification = document.EmbeddedFiles.AddEmpty(entry.Name).Value;

                        // Set embedded file description to the relative path of the file in the zip archive.
                        fileSpecification.Description = entry.FullName;

                        var embeddedFile = fileSpecification.EmbeddedFile;

                        // Set the embedded file size and modification date.
                        if (entry.Length < int.MaxValue)
                            embeddedFile.Size = (int)entry.Length;
                        embeddedFile.ModificationDate = entry.LastWriteTime;

                        // Copy embedded file contents from the zip archive entry.
                        // Embedded file is compressed if its compressed size in the zip archive is less than its uncompressed size.
                        using (var entryStream = entry.Open())
                        using (var embeddedFileStream = embeddedFile.OpenWrite(compress: entry.CompressedLength < entry.Length))
                            entryStream.CopyTo(embeddedFileStream);
                    }

            document.Save("Embedded Files from Streams.pdf");
        }
    }
}
Imports System.IO
Imports System.IO.Compression
Imports GemBox.Pdf

Module Program

    Sub Main()

        ' If using the Professional version, put your serial key below.
        ComponentInfo.SetLicense("FREE-LIMITED-KEY")

        Using document = PdfDocument.Load("%InputFileName%")

            ' Make Attachments panel visible.
            document.PageMode = PdfPageMode.UseAttachments

            ' Embed in the PDF document all the files from the zip archive.
            Using archiveStream = File.OpenRead("%#Attachments.zip%")
                Using archive = New ZipArchive(archiveStream, ZipArchiveMode.Read, leaveOpen:=True)
                    For Each entry In archive.Entries
                        If Not String.IsNullOrEmpty(entry.Name) Then

                            Dim fileSpecification = document.EmbeddedFiles.AddEmpty(entry.Name).Value

                            ' Set embedded file description to the relative path of the file in the zip archive.
                            fileSpecification.Description = entry.FullName

                            Dim embeddedFile = fileSpecification.EmbeddedFile

                            ' Set the embedded file size and modification date.
                            If entry.Length < Integer.MaxValue Then embeddedFile.Size = CInt(entry.Length)
                            embeddedFile.ModificationDate = entry.LastWriteTime

                            ' Copy embedded file contents from the zip archive entry.
                            ' Embedded file is compressed if its compressed size in the zip archive is less than its uncompressed size.
                            Using entryStream = entry.Open()
                                Using embeddedFileStream = embeddedFile.OpenWrite(compress:=entry.CompressedLength < entry.Length)
                                    entryStream.CopyTo(embeddedFileStream)
                                End Using
                            End Using
                        End If
                    Next
                End Using
            End Using

            document.Save("Embedded Files from Streams.pdf")
        End Using
    End Sub
End Module

You can see the embedded files from the previous examples in the Attachments panel. To visually represent an embedded file on a PDF page, see the File Attachment Annotations example.

The examples above use the Description property to set additional information to each embedded file. To add files with custom metadata and with a hierarchical view (using folders), see the Portfolios example.

Extract embedded files

The example below shows how to extract embedded files from an existing PDF document to a zip archive.

Upload your file (Drag file here)
using System;
using System.IO;
using System.IO.Compression;
using GemBox.Pdf;

class Program
{
    static void Main()
    {
        // If using the Professional version, put your serial key below.
        ComponentInfo.SetLicense("FREE-LIMITED-KEY");

        // Add to zip archive all files embedded in the PDF document.
        using (var document = PdfDocument.Load("%InputFileName%"))
        using (var archiveStream = File.Create("Embedded Files.zip"))
        using (var archive = new ZipArchive(archiveStream, ZipArchiveMode.Create, leaveOpen: true))
            foreach (var keyFilePair in document.EmbeddedFiles)
            {
                var fileSpecification = keyFilePair.Value;

                // Use the description or the name as the relative path of the entry in the zip archive.
                var entryFullName = fileSpecification.Description;
                if (entryFullName == null || !entryFullName.EndsWith(fileSpecification.Name, StringComparison.Ordinal))
                    entryFullName = fileSpecification.Name;

                var embeddedFile = fileSpecification.EmbeddedFile;

                // Create zip archive entry.
                // Zip archive entry is compressed if the embedded file's compressed size is less than its uncompressed size.
                bool compress = embeddedFile.Size == null || embeddedFile.CompressedSize < embeddedFile.Size.GetValueOrDefault();
                var entry = archive.CreateEntry(entryFullName, compress ? CompressionLevel.Optimal : CompressionLevel.NoCompression);

                // Set the modification date, if it is specified in the embedded file.
                var modificationDate = embeddedFile.ModificationDate;
                if (modificationDate != null)
                    entry.LastWriteTime = modificationDate.GetValueOrDefault();

                // Copy embedded file contents to the zip archive entry.
                using (var embeddedFileStream = embeddedFile.OpenRead())
                using (var entryStream = entry.Open())
                    embeddedFileStream.CopyTo(entryStream);
            }
    }
}
Imports System
Imports System.IO
Imports System.IO.Compression
Imports GemBox.Pdf

Module Program

    Sub Main()

        ' If using the Professional version, put your serial key below.
        ComponentInfo.SetLicense("FREE-LIMITED-KEY")

        ' Add to zip archive all files embedded in the PDF document.
        Using document = PdfDocument.Load("%InputFileName%")
            Using archiveStream = File.Create("Embedded Files.zip")
                Using archive = New ZipArchive(archiveStream, ZipArchiveMode.Create, leaveOpen:=True)
                    For Each keyFilePair In document.EmbeddedFiles

                        Dim fileSpecification = keyFilePair.Value

                        ' Use the description or the name as the relative path of the entry in the zip archive.
                        Dim entryFullName = fileSpecification.Description
                        If entryFullName Is Nothing OrElse Not entryFullName.EndsWith(fileSpecification.Name, StringComparison.Ordinal) Then entryFullName = fileSpecification.Name

                        Dim embeddedFile = fileSpecification.EmbeddedFile

                        ' Create zip archive entry.
                        ' Zip archive entry is compressed if the embedded file's compressed size is less than its uncompressed size.
                        Dim compress As Boolean = embeddedFile.Size Is Nothing OrElse embeddedFile.CompressedSize < embeddedFile.Size.GetValueOrDefault()
                        Dim entry = archive.CreateEntry(entryFullName, If(compress, CompressionLevel.Optimal, CompressionLevel.NoCompression))

                        ' Set the modification date, if it is specified in the embedded file.
                        Dim modificationDate = embeddedFile.ModificationDate
                        If modificationDate IsNot Nothing Then entry.LastWriteTime = modificationDate.GetValueOrDefault()

                        ' Copy embedded file contents to the zip archive entry.
                        Using embeddedFileStream = embeddedFile.OpenRead()
                            Using entryStream = entry.Open()
                                embeddedFileStream.CopyTo(entryStream)
                            End Using
                        End Using
                    Next
                End Using
            End Using
        End Using
    End Sub
End Module

See also


Next steps

GemBox.Pdf is a .NET component that enables developers to read, merge and split PDF files or execute low-level object manipulations from .NET applications in a simple and efficient way.

Download Buy