Как извлечь вложения из файла PDF? - PullRequest
8 голосов
/ 10 июня 2011

У меня есть большое количество PDF-документов с прикрепленными к ним XML-файлами.Я хотел бы извлечь эти прикрепленные файлы XML и прочитать их.Как я могу сделать это программно, используя .net?

Ответы [ 5 ]

7 голосов
/ 13 июня 2011

iTextSharp также вполне способен извлекать вложения ... Хотя для этого может потребоваться использование объектов низкого уровня.

Существует два способа встраивания файлов в PDF:

  1. В аннотации файла
  2. На уровне документа "EmbeddedFiles".

Если у вас есть словарь спецификации файлов из любого источника, сам файл будет потоком внутрисловарь с надписью «EF» (встроенный файл).

Таким образом, чтобы вывести список всех файлов на уровне документа, можно написать код (на Java) следующим образом:

Map<String, byte[]> files = new HashMap<String,byte[]>();

PdfReader reader = new PdfReader(pdfPath);
PdfDictionary root = reader.getCatalog();
PdfDictionary names = root.getAsDict(PdfName.NAMES); // may be null
PdfDictionary embeddedFilesDict = names.getAsDict(PdfName.EMBEDDEDFILES); //may be null
PdfArray embeddedFiles = embeddedFilesDict.getAsArray(PdfName.NAMES); // may be null

int len = embeddedFiles.size();
for (int i = 0; i < len; i += 2) {
  PdfString name = embeddedFiles.getAsString(i); // should always be present
  PdfDictionary fileSpec = embeddedFiles.getAsDict(i+1); // ditto

  PdfDictionary streams = fileSpec.getAsDict(PdfName.EF);
  PRStream stream = null;

  if (streams.contains(PdfName.UF))
    stream = (PRStream)streams.getAsStream(PdfName.UF);
  else
    stream = (PRStream)streams.getAsStream(PdfName.F); // Default stream for backwards compatibility

  if (stream != null) {
    files.put( name.toUnicodeString(), PdfReader.getStreamBytes((PRStream)stream));
  }
}
4 голосов
/ 03 января 2013

Это старый вопрос, тем не менее, я думаю, что мое альтернативное решение (с использованием PDF Clown ) может представлять некоторый интерес, так как это намного чище (и более полно, поскольку он повторяется как на уровне документа, так и на уровне страницы) , чем ранее предложенные фрагменты кода:

using org.pdfclown.bytes;
using org.pdfclown.documents;
using org.pdfclown.documents.files;
using org.pdfclown.documents.interaction.annotations;
using org.pdfclown.objects;

using System;
using System.Collections.Generic;

void ExtractAttachments(string pdfPath)
{
  Dictionary<string, byte[]> attachments = new Dictionary<string, byte[]>();

  using(org.pdfclown.files.File file = new org.pdfclown.files.File(pdfPath))
  {
    Document document = file.Document;

    // 1. Embedded files (document level).
    foreach(KeyValuePair<PdfString,FileSpecification> entry in document.Names.EmbeddedFiles)
    {EvaluateDataFile(attachments, entry.Value);}

    // 2. File attachments (page level).
    foreach(Page page in document.Pages)
    {
      foreach(Annotation annotation in page.Annotations)
      {
        if(annotation is FileAttachment)
        {EvaluateDataFile(attachments, ((FileAttachment)annotation).DataFile);}
      }
    }
  }
}

void EvaluateDataFile(Dictionary<string, byte[]> attachments, FileSpecification dataFile)
{
  if(dataFile is FullFileSpecification)
  {
    EmbeddedFile embeddedFile = ((FullFileSpecification)dataFile).EmbeddedFile;
    if(embeddedFile != null)
    {attachments[dataFile.Path] = embeddedFile.Data.ToByteArray();}
  }
}

Обратите внимание, что вам не нужно беспокоиться об исключениях нулевого указателя , поскольку PDF Clown обеспечивает всю необходимую абстракцию и автоматизацию для обеспечения плавного обхода модели.

PDF Clown - это библиотека LGPL 3, реализованная как на платформах Java, так и на платформе .NET (я являюсь ее ведущим разработчиком): если вы хотите попробовать, я предлагаю вам проверить ее репозиторий SVN на sourceforge.net как он продолжает развиваться.

2 голосов
/ 15 августа 2012

То, что я получил, немного отличается от всего, что я видел в Интернете.

Так, на всякий случай, я подумал, что опубликую это здесь, чтобы помочь кому-то еще. Мне пришлось пройти через много разных итераций, чтобы понять - трудный путь - что мне нужно, чтобы заставить его работать.

Я объединяю два PDF-файла в третий PDF-файл, где один из первых двух PDF-файлов может иметь вложения файлов, которые необходимо перенести в третий PDF-файл. Я полностью работаю в потоках с ASP.NET, C # 4.0, ITextSharp 5.1.2.0.

        // Extract Files from Submit PDF
        Dictionary<string, byte[]> files = new Dictionary<string, byte[]>();

        PdfDictionary names;
        PdfDictionary embeddedFiles;
        PdfArray fileSpecs;
        int eFLength = 0;


        names = writeReader.Catalog.GetAsDict(PdfName.NAMES); // may be null, writeReader is the PdfReader for a PDF input stream
        if (names != null)
        {
            embeddedFiles = names.GetAsDict(PdfName.EMBEDDEDFILES); //may be null
            if (embeddedFiles != null)
            {
                fileSpecs = embeddedFiles.GetAsArray(PdfName.NAMES); //may be null
                if (fileSpecs != null)
                {
                    eFLength = fileSpecs.Size;

                    for (int i = 0; i < eFLength; i++)
                    {
                        i++; //objects are in pairs and only want odd objects (1,3,5...)
                        PdfDictionary fileSpec = fileSpecs.GetAsDict(i); // may be null
                        if (fileSpec != null)
                        {
                            PdfDictionary refs = fileSpec.GetAsDict(PdfName.EF);
                            foreach (PdfName key in refs.Keys)
                            {
                                PRStream stream = (PRStream)PdfReader.GetPdfObject(refs.GetAsIndirectObject(key));

                                if (stream != null)
                                {
                                    files.Add(fileSpec.GetAsString(key).ToString(), PdfReader.GetStreamBytes(stream));
                                }
                            }
                        }
                    }
                }
            }
        }
2 голосов
/ 10 июня 2011

Ищите ABCpdf - Библиотека, на мой взгляд, очень простая и быстрая.

1 голос
/ 20 июня 2011

Вы можете попробовать Aspose.Pdf.Kit для .NET . Класс PdfExtractor позволяет извлекать вложения с помощью двух методов: ExtractAttachment и GetAttachment. Пожалуйста, смотрите пример извлечения вложений .

Раскрытие информации: я работаю евангелистом-разработчиком в Aspose.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...