2009-02-19 8 views
7

Ho setacciato il Web alla ricerca di esempi su come farlo. Ho trovato alcuni che sembrano essere un po 'più coinvolti, quindi devono essere. Quindi la mia domanda è, usando iTextSharp, c'è un modo abbastanza conciso per aggiungere un documento PDF ad un altro?Esiste un modo semplice per aggiungere un documento PDF a un altro utilizzando iTextSharp?

In modo ottimale, questo NON comporterebbe un terzo file. Basta aprire il primo documento PDF, aggiungere il secondo documento PDF al primo e quindi chiuderli entrambi.

risposta

5

Ok, non è semplice, ma funziona ed è sorprendentemente veloce. (E usa un terzo file, niente di simile a open e append.) Ho 'scoperto' questo nei documenti/esempi. Ecco il codice:

private void CombineMultiplePDFs(string[] fileNames, string outFile) { 
    int pageOffset = 0; 
    ArrayList master = new ArrayList(); 
    int f = 0; 

    Document document = null; 
    PdfCopy writer = null; 
    while (f < fileNames.Length) { 
     // we create a reader for a certain document 
     PdfReader reader = new PdfReader(fileNames[ f ]); 
     reader.ConsolidateNamedDestinations(); 
     // we retrieve the total number of pages 
     int n = reader.NumberOfPages; 
     ArrayList bookmarks = SimpleBookmark.GetBookmark(reader); 
     if (bookmarks != null) { 
      if (pageOffset != 0) { 
       SimpleBookmark.ShiftPageNumbers(bookmarks, pageOffset, null); 
      } 
      master.AddRange(bookmarks); 
     } 
     pageOffset += n; 

     if (f == 0) { 
      // step 1: creation of a document-object 
      document = new Document(reader.GetPageSizeWithRotation(1)); 
      // step 2: we create a writer that listens to the document 
      writer = new PdfCopy(document, new FileStream(outFile, FileMode.Create)); 
      // step 3: we open the document 
      document.Open(); 
     } 
     // step 4: we add content 
     for (int i = 0; i < n;) { 
      ++i; 
      if (writer != null) { 
       PdfImportedPage page = writer.GetImportedPage(reader, i); 
       writer.AddPage(page); 
      } 
     } 
     PRAcroForm form = reader.AcroForm; 
     if (form != null && writer != null) { 
      writer.CopyAcroForm(reader); 
     } 
     f++; 
    } 
    if (master.Count > 0 && writer != null) { 
     writer.Outlines = master; 
    } 
    // step 5: we close the document 
    if (document != null) { 
     document.Close(); 
    } 
} 
1

Sì. Ho visto una classe chiamata PdfManipulation pubblicata in un forum iText. L'uso di quella classe implicherebbe comunque un terzo file.

La classe è originariamente in VB.Net. L'ho scaricato da un post on vbforums.com. Apparentemente però, non ha la funzione di unione dei file, quindi ne ho scritto uno basato sul codice di quella classe.

Questo è stato scritto su una macchina senza iTextSharp. Questo potrebbe avere bug. Non sono nemmeno sicuro che i numeri di pagina siano basati su 0 o su base 1. Ma dagli un colpo.

public static void MergePdfFiles(IEnumerable<string> files, string output) { 
    iTextSharp.text.Document doc; 
    iTextSharp.text.pdf.PdfCopy pdfCpy; 

    doc = new iTextSharp.text.Document(); 
    pdfCpy = new iTextSharp.text.pdf.PdfCopy(doc, new System.IO.FileStream(output, System.IO.FileMode.Create)); 
    doc.Open(); 

    foreach (string file in files) { 
     // initialize a reader 
     iTextSharp.text.pdf.PdfReader reader = new iTextSharp.text.pdf.PdfReader(file); 
     int pageCount = reader.NumberOfPages; 

     // set page size for the documents 
     doc.SetPageSize(reader.GetPageSizeWithRotation(1)); 

     for (int pageNum = 1; pageNum <= pageCount; pageNum++) { 
      iTextSharp.text.pdf.PdfImportedPage page = pdfCpy.GetImportedPage(reader, pageNum); 
      pdfCpy.AddPage(page); 
     } 

     reader.Close(); 
    } 

    doc.Close(); 
} 
+1

numeri di pagina sono a base 1 –

0

Non so come farlo per i file PDF, ma per PostScript, basta concatenare i file. Se si dispone di pdf2ps e ps2pdf installati, il seguito farà il lavoro:

pdf2ps file1.pdf file1.ps 
pdf2ps file2.pdf file2.ps 
cat file1.ps file2.ps > combined.ps 
ps2pdf combined.ps combined.pdf 

Io non sono un esperto di pdf2ps o ps2pdf. Ho sempre usato solo ps2pdf e, quando lo faccio, lascia il testo come testo (posso ancora selezionare e copiare il testo dal pdf ottenuto). Quando faccio i passaggi sopra (pdf-> ps, combine, ps-> pdf) finisco con un pdf risultante che è come un'immagine. Non ho idea del perché.

13

Mi può davvero mancare qualcosa, ma ho fatto qualcosa di molto più semplice. Concedo che questa soluzione probabilmente non aggiornerà i segnalibri (come nella migliore risposta qui finora), ma funziona perfettamente per me. Poiché stavo unendo i documenti con moduli compilabili, ho usato PdfCopyFields anziché PdfCopy.

Ecco il codice (che ho messo a nudo tutta la gestione per rendere il codice vero e proprio più visibile errore, aggiungere un try..finally per chiudere le risorse aperti se si pensa di utilizzare il codice):

void MergePdfStreams(List<Stream> Source, Stream Dest) 
    { 
     PdfCopyFields copy = new PdfCopyFields(Dest); 

     foreach (Stream source in Source) 
     { 
      PdfReader reader = new PdfReader(source); 
      copy.AddDocument(reader); 
     } 

     copy.Close(); 
    } 

è possibile passare qualsiasi flusso, sia esso un FileStream, un MemoryStream (utile quando la lettura del PDF da banche dati, senza bisogno di file temporanei, ecc)

Esempio utilizzo:

void TestMergePdfStreams() 
    { 
     List<Stream> sources = new List<Stream>() 
     { 
      new FileStream("template1.pdf", FileMode.Open), 
      new FileStream("template2.pdf", FileMode.Open), 
      new MemoryStream((byte[])someDataRow["PDF_COLUMN_NAME"]) 
     }; 

     MergePdfStreams(sources, new FileStream("MergedOutput.pdf", FileMode.Create)); 
    } 
+1

Ciò ha funzionato perfettamente per provare a unire/aggiungere due documenti PDF con Campi modulo! Molto più semplice! Grazie. –

+0

Questo ha funzionato benissimo per me. Suggerirei di chiamare source.Close() dopo la chiamata copy.AddDocument per consentire al file di funzionare con altrove. – Jason