2016-11-01 2 views
0

Ich versuche, PDF-Dateien (potenziell 1000 von ihnen) in einer Streaming-Mode zu verschmelzen, so dass ich nicht alle Dokumente in den Speicher laden oder erstellen Sie ein Monster PDF-Ausgabe ist in den Speicher geladen.PDF-Dateien mit iTextSharp in Ausgabe-Stream verschmelzen

Für meine Funktion gebe ich einfach einen Verzeichnisnamen, der alle PDFs enthält zusammen mit einer Ausgabe Stream zu schreiben, um zu schreiben.

private void MergePDFDocuments(string batchFilesFolder, Stream outputStream) 
{ 
    using (var batchDocument = new iTextSharp.text.Document()) 
    using (var writer = iTextSharp.text.pdf.PdfWriter.GetInstance(batchDocument, outputStream)) 
    { 
     batchDocument.Open(); 

     var cb = writer.DirectContent; 

     foreach (var file in new DirectoryInfo(batchFilesFolder).GetFiles("*.pdf")) 
     { 
      // we create a reader for the document 
      using (var reader = new iTextSharp.text.pdf.PdfReader(file.FullName)) 
      { 
       int i = 0; 
       while (i < reader.NumberOfPages) 
       { 
        i++; 
        batchDocument.SetPageSize(reader.GetPageSizeWithRotation(1)); 
        batchDocument.NewPage(); 

        var page = writer.GetImportedPage(reader, i); 
        var rotation = reader.GetPageRotation(i); 

        if (rotation == 90 || rotation == 270) 
        { 
         cb.AddTemplate(page, 0, -1f, 1f, 0, 0, reader.GetPageSizeWithRotation(i).Height); 
        } 
        else 
        { 
         cb.AddTemplate(page, 1f, 0, 0, 1f, 0, 0); 
        } 
       } 
      } 
     } 
    } 
} 

Allerdings, wenn ich diesen Code ausführen, erhalte ich eine ‚System.ObjectDisposedException Ausnahme: Es kann keine geschlossene Datei zugreifen zu können.‘ Ausnahme. Hier ist der Aufruf-Stack.

at System.IO.__Error.FileNotOpen() 
    at System.IO.FileStream.get_Position() 
    at iTextSharp.text.io.RAFRandomAccessSource.Get(Int64 position, Byte[] bytes, Int32 off, Int32 len) 
    at iTextSharp.text.io.IndependentRandomAccessSource.Get(Int64 position, Byte[] bytes, Int32 off, Int32 len) 
    at iTextSharp.text.pdf.RandomAccessFileOrArray.Read(Byte[] b, Int32 off, Int32 len) 
    at iTextSharp.text.pdf.RandomAccessFileOrArray.ReadFully(Byte[] b, Int32 off, Int32 len) 
    at iTextSharp.text.pdf.RandomAccessFileOrArray.ReadFully(Byte[] b) 
    at iTextSharp.text.pdf.PdfReader.GetStreamBytesRaw(PRStream stream, RandomAccessFileOrArray file) 
    at iTextSharp.text.pdf.PdfReader.GetStreamBytesRaw(PRStream stream) 
    at iTextSharp.text.pdf.PRStream.ToPdf(PdfWriter writer, Stream os) 
    at iTextSharp.text.pdf.PdfIndirectObject.WriteTo(Stream os) 
    at iTextSharp.text.pdf.PdfWriter.PdfBody.Write(PdfIndirectObject indirect, Int32 refNumber, Int32 generation) 
    at iTextSharp.text.pdf.PdfWriter.PdfBody.Add(PdfObject objecta, Int32 refNumber, Int32 generation, Boolean inObjStm) 
    at iTextSharp.text.pdf.PdfWriter.AddToBody(PdfObject objecta, PdfIndirectReference refa) 
    at iTextSharp.text.pdf.PdfReaderInstance.WriteAllPages() 
    at iTextSharp.text.pdf.PdfWriter.AddSharedObjectsToBody() 
    at iTextSharp.text.pdf.PdfWriter.Close() 
    at iTextSharp.text.pdf.PdfDocument.Close() 
    at iTextSharp.text.pdf.PdfWriter.Close() 
    at iTextSharp.text.DocWriter.Dispose() 
    at BTR.Evolution.Legacy.Jobs.BatchDocGen.MergePDFDocuments(String batchFilesFolder, Stream outputStream) in C:\BTR\Source\Evolution\BTR.Evolution\Legacy.Jobs\BatchDocGen.cs:line 598 
+3

Dokument mit 'PdfWriter' zusammenführen? Das verursacht viele Probleme. Siehe [Wie Dokumente korrekt zusammengeführt werden?] (Http://developers.itextpdf.com/question/how-merge-documents-correctly) Außerdem: Sie schließen den 'PdfReader' implizit. Wenn ich Sie wäre, würde ich zu iText 7 für C# bewegen, anstatt iTextSharp zu verwenden. Viele Dinge haben sich verbessert, als wir iText von Grund auf neu geschrieben haben. –

+0

@BrunoLowagie Von Ihrem Link nehme ich an, ich würde das 'PdfSmartCopy'-Beispiel verwenden? Wenn dieses Muster folgt, befindet sich das gesamte Ausgabedokument während der Erstellung im Speicher oder wird das Dokument in die Ausgabe "Stream" gestreamt? – Terry

+0

iText wird versuchen, so viele Seiten wie möglich in den Ausgabestream zu streamen, aber Sie müssen Konzepte wie das Freigeben der Leserinstanz verwenden. Suchen Sie nach der 'freeReader()' Methode. Wenn Sie diese Methode nicht verwenden, verbrauchen alle Ihre Reader-Instanzen viel Speicher. –

Antwort

0

Ich wette, dass Ihr Parameter 'outputStream' geschlossen ist. Rufen Sie diese Methode zweimal an? Wenn Ihre Variable "Writer" entsorgt wird, wird der zugrunde liegende Stream geschlossen.

+0

ich nur anrufen die Methode einmal. Ich testete mit dem Verzeichnis von 2 Dokumenten, und sobald es zum ersten (und einzigen) Mal das Ende von 'batchDocument/writer' erreicht, löst es die Ausnahme aus. – Terry

+1

Auf den ersten Blick würde ich sagen, es ist kein Problem des 'outputStream'. Die Fehlermeldung zeigt in Richtung PdfReader. Der 'PdfReader' wird geschlossen, bevor er gelesen werden kann. Die Reader-Objekte sind geschlossen, wenn die 'using'-Klammern geschlossen sind. Das ist wahrscheinlich zu früh. –