2017-09-08 36 views
0

我試圖使用下面的代碼合併文件夾中的pdf文件並輸出到一個新的文件,但顯然生成的文件似乎損壞。使用itextsharp合併文件夾內的pdf文件

public Boolean MergeForm(String destinationFile, String sourceFolder) 
    { 
     try 
     { 
      using (MemoryStream stream = new MemoryStream()) 
      using (Document doc = new Document()) 
      using (PdfCopy pdf = new PdfCopy(doc, stream)) 
      { 
       doc.Open(); 

       PdfReader reader = null; 
       PdfImportedPage page = null; 

       foreach (var file in Directory.GetFiles(sourceFolder)) 
       { 
        reader = new PdfReader(file); 
        for (int i = 0; i < reader.NumberOfPages; i++) 
        { 
         page = pdf.GetImportedPage(reader, i + 1); 
         pdf.AddPage(page); 
        } 

        pdf.FreeReader(reader); 
        reader.Close(); 
       } 
       using (FileStream streamX = new FileStream(destinationFile, FileMode.Create)) 
       { 
        stream.WriteTo(streamX); 
       } 
      } 
      return true; 
     } 
     catch (Exception) 
     { 
      return false; 
     } 
    } 

任何人都可以發現問題在哪裏?謝謝。

+0

這看起來非常像最近的問題的重複[使用PdfCopy合併PDF文件(https://stackoverflow.com/questions/45951966/using-pdfcopy-to-merge-pdf-files)。爲什麼不使用AddDocument()方法而不是循環遍歷不同的頁面,並且一次只添加一個頁面?您是否正在使用最新版本的iText? –

+0

但是,主要問題是您正在編寫文件的那一刻。當你做'stream.WriteTo(streamX)'時,'Document'實例還沒有關閉。這意味着寫入'streamX'的PDF不完整。大量的信息(如交叉引用表,字體,PDF預告片)缺失。當docClose()發生時,這些信息只能添加到'stream'中。在你的情況下,當*'stream.WriteTo(streamX)'後面的括號*中的一個被隱式地發生時。 –

+0

@BrunoLowagie我正在使用itextsharp 5.5.12.0。 btw,如何修改代碼以使用AddDocument? 我會看看你在這裏分享的另一個線索,謝謝。 – Trowa

回答

2

任何人都可以發現問題在哪裏?

你的主要問題是,你使用MemoryStream內容的DocumentPdfCopy之前已經完成(在using塊的末尾Dispose期間)創建PDF。因此,您保存了一個不完整的PDF文件。

做它像這樣反而應該工作:

using (MemoryStream stream = new MemoryStream()) 
    { 
     using (Document doc = new Document()) 
     { 
      PdfCopy pdf = new PdfCopy(doc, stream); 
      pdf.CloseStream = false; 
      doc.Open(); 

      PdfReader reader = null; 
      PdfImportedPage page = null; 

      foreach (var file in Directory.GetFiles(sourceFolder)) 
      { 
       reader = new PdfReader(file); 
       for (int i = 0; i < reader.NumberOfPages; i++) 
       { 
        page = pdf.GetImportedPage(reader, i + 1); 
        pdf.AddPage(page); 
       } 

       pdf.FreeReader(reader); 
       reader.Close(); 
      } 
     } 
     using (FileStream streamX = new FileStream(destinationFile, FileMode.Create)) 
     { 
      stream.WriteTo(streamX); 
     } 
    } 

順便說一句,你還看到這裏,我並沒有把PdfCopyusing塊。這是因爲Document在處置時隱式關閉了PDFCopy。因此,首先處置PdfCopy然後Document(其試圖再次關閉PdfCopy)不是必需的,並且可能導致隱藏在該閉包中發生的其他異常從塊內拋出的異常。

此外我需要添加pdf.CloseStream = false,否則當PdfCopy關閉時內存流將被關閉。


也有人說,

  1. 當然,你也應該使用AddDocument,而不是遍歷自己被@Bruno已經說明文檔頁面。
  2. 如果您立即寫入文件流而不是內存流,則內存佔用將減少。