2016-11-01 3 views
0

나는 모든 문서를 메모리에로드하거나 하나의 괴물 출력 PDF를 만들 필요가 없도록 스트리밍 방식으로 PDF 파일 (잠재적으로 그 중 1000 개)을 병합하려고합니다. 메모리에로드됩니다.iTextSharp를 사용하여 PDF 파일을 출력 스트림으로 병합

제 기능을 위해, 병합 할 모든 PDF가 들어있는 디렉토리 이름을 출력하려면 Stream으로 작성하십시오.

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

그러나이 코드를 실행하면 'System.ObjectDisposedException Exception : 닫힌 파일에 액세스 할 수 없습니다'라는 메시지가 나타납니다. 예외. 다음은 호출 스택입니다.

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

'PdfWriter'로 문서를 병합 하시겠습니까? 그 때문에 많은 문제가 발생합니다. [문서를 올바르게 병합하는 방법?] (http://developers.itextpdf.com/question/how-merge-documents-correctly) 참고 : 또한'PdfReader'를 암시 적으로 닫고 있습니다. 내가 너라면 iTextSharp를 사용하는 대신 C# 용 iText 7로 이동하겠다. 우리가 처음부터 iText를 다시 작성할 때 많은 것들이 향상되었습니다. –

+0

@BrunoLowagie 귀하의 링크에서, 나는'PdfSmartCopy' 샘플을 사용한다고 가정합니까? 이 패턴을 따르는 경우, 생성 중에는 전체 출력 문서가 메모리에 있거나 출력 스트림에 '스트리밍'된 문서가 생성됩니까? – Terry

+0

iText는 최대한 많은 페이지를 출력 스트림에 스트리밍하려고 시도하지만 독자 인스턴스를 해제하는 것과 같은 개념을 사용해야합니다. 'freeReader()'메소드를 찾는다. 이 방법을 사용하지 않으면 모든 리더 인스턴스가 많은 메모리를 소비합니다. –

답변

0

'outputStream'매개 변수가 닫혔습니다. 이 방법을 두 번 부르십니까? 변수 'writer'가 처리되면 기본 스트림이 닫힙니다.

+0

전화 만 있습니다. 한 번 방법. 필자는 2 개의 문서 디렉토리를 가지고 테스트했고, 첫 번째 (그리고 유일한) 시간에'using batchDocument/writer'의 끝에 도달하자마자 예외를 던졌습니다. – Terry

+1

첫눈에, 나는 그것이'outputStream'의 문제가 아니라고 말하고 싶습니다. 오류 메시지는'PdfReader'의 방향을 가리 킵니다. 'PdfReader'는 읽히기 전에 닫힙니다. reader 객체는'using '대괄호가 닫힐 때 닫힙니다. 아마도 너무 일찍입니다. –

관련 문제