Работа с большими PDF документами в .NET

Категория: PDF.NET

5 февраля 2021

PDF спецификация определяет, что PDF документ версии 1.0-1.4 не может иметь размер больший чем 9,3GB (9.999.999.999 байт).
PDF версии 1.5 и выше не ограничивают размер PDF файла, если PDF документ использует Compressed Cross-Reference Table.

VintaSoft Imaging .NET SDK позволяет создавать, открывать, изменять и сохранять PDF документ версии 1.0-1.4, если размер файла не превышает 9,3GB (9.999.999.999 байт).
SDK позволяет создавать, открывать, изменять и сохранять PDF документ версии 1.5 и выше в котором используется Compressed Cross-Reference Table, если размер файла не превышает 256TB (281.474.976.710.655 байт).

PDF спецификация не ограничивает размер вложенного файла хранимого в PDF документе.
VintaSoft Imaging .NET SDK позволяет добавлять вложенные файлы в PDF документ. В общем случае, SDK может добавить вложенный файл в PDF документ, если его размер не превышает 2GB (2.147.483.647 байт). Также SDK позволяет добавить вложенный файл размер которого превышает 2GB, но не превышает 931GB (999.999.999.999 байт), если PDF документ не зашифрован и ресурс добавляется без сжатия либо с ZIP сжатием.
Для извлечения ресурса из PDF документа действуют те же ограничения по размеру ресурса, что и при добавлении ресурса в PDF документ.


Вот C# код, который демонстрирует как добавить и извлечь вложение в PDF документ, если размер вложения превышает 2GB:
/// <summary>
/// Adds the large file attachment to PDF document.
/// </summary>
/// <param name="pdfFilename">The PDF filename.</param>
/// <param name="attachmentFilename">The attachment filename.</param>
public static void AddLargeAttachment(string pdfFilename, string attachmentFilename)
{
    // open PDF document
    using (Vintasoft.Imaging.Pdf.PdfDocument document = new Vintasoft.Imaging.Pdf.PdfDocument(pdfFilename))
    {
        if (document.EmbeddedFiles == null)
            document.EmbeddedFiles = new Vintasoft.Imaging.Pdf.Tree.PdfEmbeddedFileSpecificationDictionary(document);

        // open attachment file
        using (System.IO.Stream attachmentStream = System.IO.File.OpenRead(attachmentFilename))
        {
            // set ZIP compression level to 2 (fast)
            Vintasoft.Imaging.Pdf.PdfCompressionSettings compressionSettings = new Vintasoft.Imaging.Pdf.PdfCompressionSettings();
            compressionSettings.ZipCompressionLevel = 2;

            // create PDF embedded file
            Vintasoft.Imaging.Pdf.Tree.PdfEmbeddedFile embeddedFile = new Vintasoft.Imaging.Pdf.Tree.PdfEmbeddedFile(
                document, attachmentStream, false, Vintasoft.Imaging.Pdf.PdfCompression.Zip, compressionSettings);
            
            // create PDF embedded file specification
            Vintasoft.Imaging.Pdf.Tree.PdfEmbeddedFileSpecification fileSpecification =
                 new Vintasoft.Imaging.Pdf.Tree.PdfEmbeddedFileSpecification(System.IO.Path.GetFileName(attachmentFilename), embeddedFile);

            // add PDF embedded file specification to PDF document
            document.EmbeddedFiles.Add(fileSpecification);

            // save changes in PDF document (file attachment will be encoded during saving of PDF document)
            document.SaveChanges();
        }
    }
}

/// <summary>
/// Extracts the file attachments of PDF document in specified folder.
/// </summary>
/// <param name="pdfFilename">The PDF filename.</param>
/// <param name="attachmentOutputDir">The attachment output directory.</param>
public static void ExtractFileAttachments(string pdfFilename, string attachmentOutputDir)
{
    // open PDF document
    using (Vintasoft.Imaging.Pdf.PdfDocument document = new Vintasoft.Imaging.Pdf.PdfDocument(pdfFilename))
    {
        // if PDF document has embedded files
        if (document.EmbeddedFiles != null)
        {
            // for each file embedded in PDF document
            foreach (Vintasoft.Imaging.Pdf.Tree.PdfEmbeddedFileSpecification fileSpecification in document.EmbeddedFiles.Values)
            {
                if (fileSpecification.EmbeddedFile != null)
                {
                    // save embedded file resource to a file in output directory
                    string filename = System.IO.Path.GetFileName(fileSpecification.Filename);
                    fileSpecification.EmbeddedFile.Save(System.IO.Path.Combine(attachmentOutputDir, filename));
                }
            }
        }
    }
}


Вот C# код, который демонстрирует как добавить и извлечь вложение в PDF документ, если размер вложения не превышает 2GB:
/// <summary>
/// Adds the file attachment to PDF document.
/// </summary>
/// <param name="pdfFilename">The PDF filename.</param>
/// <param name="attachmentFilename">The attachment filename.</param>
public static void AddAttachment(string pdfFilename, string attachmentFilename)
{
    // open PDF document
    using (Vintasoft.Imaging.Pdf.PdfDocument document = new Vintasoft.Imaging.Pdf.PdfDocument(pdfFilename))
    {
        if (document.EmbeddedFiles == null)
            document.EmbeddedFiles = new Vintasoft.Imaging.Pdf.Tree.PdfEmbeddedFileSpecificationDictionary(document);

        // create PDF embedded file (file attachment will be encoded in constructor of PdfEmbeddedFile class)
        Vintasoft.Imaging.Pdf.Tree.PdfEmbeddedFile embeddedFile = new Vintasoft.Imaging.Pdf.Tree.PdfEmbeddedFile(
            document, attachmentFilename, Vintasoft.Imaging.Pdf.PdfCompression.Zip);

        // create PDF embedded file specification
        Vintasoft.Imaging.Pdf.Tree.PdfEmbeddedFileSpecification fileSpecification =
             new Vintasoft.Imaging.Pdf.Tree.PdfEmbeddedFileSpecification(System.IO.Path.GetFileName(attachmentFilename), embeddedFile);

        // add PDF embedded file specification to PDF document
        document.EmbeddedFiles.Add(fileSpecification);

        // save PDF document
        document.SaveChanges();
    }
}

/// <summary>
/// Extracts the file attachments of PDF document in specified folder.
/// </summary>
/// <param name="pdfFilename">The PDF filename.</param>
/// <param name="attachmentOutputDir">The attachment output directory.</param>
public static void ExtractFileAttachments(string pdfFilename, string attachmentOutputDir)
{
    // open PDF document
    using (Vintasoft.Imaging.Pdf.PdfDocument document = new Vintasoft.Imaging.Pdf.PdfDocument(pdfFilename))
    {
        // if PDF document has embedded files
        if (document.EmbeddedFiles != null)
        {
            // for each file embedded in PDF document
            foreach (Vintasoft.Imaging.Pdf.Tree.PdfEmbeddedFileSpecification fileSpecification in document.EmbeddedFiles.Values)
            {
                if (fileSpecification.EmbeddedFile != null)
                {
                    // save embedded file resource to a file in output directory
                    string filename = System.IO.Path.GetFileName(fileSpecification.Filename);
                    fileSpecification.EmbeddedFile.Save(System.IO.Path.Combine(attachmentOutputDir, filename));
                }
            }
        }
    }
}