2011-06-10 26 views
5

Tengo un gran número de documentos pdf con archivos xml adjuntos. Me gustaría extraer esos archivos xml adjuntos y leerlos. ¿Cómo puedo hacer esto programáticamente usando .net?¿Cómo extraigo los archivos adjuntos de un archivo pdf?

+0

Gran pregunta, es de mucha ayuda, pero, ¿puedo extraer los archivos adjuntos del archivo pdf con javascript o jquery –

Respuesta

6

iTextSharp también es bastante capaz de extraer archivos adjuntos ... ugh ... aunque puede que tenga que usar los objetos de bajo nivel para hacerlo.

Hay dos maneras de incorporar archivos en formato PDF:

  1. En una anotación del archivo
  2. En los "EmbeddedFiles" nivel de documento.

Una vez que tenga un diccionario de especificación de archivo de cualquiera de las fuentes, el archivo estará en una secuencia con la etiqueta "EF" (archivo incrustado).

Así que para una lista de todos los archivos en el nivel del documento, se podría escribir código (en Java) de esta manera:

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 
PdfArray embeddedFiles = names.getAsArray(PdfName.EMBEDDEDFILES); //may be null 
int len = embeddedFiles.size(); 
for (int i = 0; i < len; i += 2) { 
    PdfName name = embeddedFiles.getAsName(i); // should always be present 
    PdfDictionary fileSpec = embeddedFiles.getAsDict(i+1); // ditto 
    PRStream stream = (PRStream)fileSpec.getAsStream(PdfName.EF); 
    if (stream != null) { 
    files.put(PdfName.decodeName(name.toString()), stream.getBytes()); 
    } 
} 
+0

gracias por la sugerencia. Voy a probar esto. +1 para la muestra de código. – gyurisc

+0

Tengo problemas con esta línea PdfArray embeddedFiles = names.getAsDictionary (PdfName.EMBEDDEDFILES); El compilador dice que no puede convertir un PdfDictionary a PdfArray – gyurisc

+0

Vaya. Eso es lo que sucede cuando escribes código en un navegador. Debería llamar a 'getAsArray()'. –

2

Busque ABCpdf -Library, muy fácil y rápido en mi opinión.

+1

gracias por la sugerencia voy a darle una oportunidad. – gyurisc

1

Puede intentar Aspose.Pdf.Kit for .NET. La clase PdfExtractor le permite extraer archivos adjuntos con la ayuda de dos métodos: ExtractAttachment y GetAttachment. Por favor vea un example of attachment extraction.

Divulgación: trabajo como desarrollador evangelista en Aspose.

1

Lo que obtuve trabajando es ligeramente diferente a cualquier otra cosa que haya visto en línea.

Así que, por las dudas, pensé que podría publicar esto aquí para ayudar a alguien más. Tuve que pasar por muchas iteraciones diferentes para descubrir, por las malas, lo que necesitaba para que funcionara.

Estoy fusionando dos archivos PDF en un tercer PDF, donde uno de los primeros dos archivos PDF puede tener archivos adjuntos que deben ser transferidos al tercer PDF. Estoy trabajando completamente en streams con 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

Se trata de una cuestión de edad, sin embargo, creo que mi solución alternativa (usando PDF Clown) puede ser de algún interés como Es la manera más limpia (y más completa, ya que itera tanto en el documento como de páginas) de los fragmentos de código previamente propuestos:

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();} 
    } 
} 

tenga en cuenta que usted no tiene que molestarse con las excepciones de puntero nulo como PDF payaso proporciona toda la abstracción y automatización necesaria para garantizar el modelo de recorrido suave.

PDF Clown es una biblioteca LGPL 3, implementada tanto en plataformas Java como .NET (soy su desarrollador principal): si quiere probarlo, le sugiero que consulte su repositorio SVN en sourceforge. neta, ya que sigue evolucionando.

+0

Gracias por agregar su solución. ¡Es muy útil! – gyurisc

Cuestiones relacionadas