2013-03-22 112 views
2

這是我如何拆分大的PDF(144 MB)iTextSharp的:分裂的頁面大小等於文件大小

public int SplitAndSave(string inputPath, string outputPath) 
    { 
     FileInfo file = new FileInfo(inputPath); 
     string name = file.Name.Substring(0, file.Name.LastIndexOf(".")); 

     using (PdfReader reader = new PdfReader(inputPath)) 
     { 

      for (int pagenumber = 1; pagenumber <= reader.NumberOfPages; pagenumber++) 
      { 
       string filename = pagenumber.ToString() + ".pdf"; 

       Document document = new Document(); 
       PdfCopy copy = new PdfCopy(document, new FileStream(outputPath + "\\" + filename, FileMode.Create)); 

       document.Open(); 

       copy.AddPage(copy.GetImportedPage(reader, pagenumber)); 

       document.Close(); 
      } 
      return reader.NumberOfPages; 
     } 

    } 

對於大多數PDF文件(小尺寸,我想老格式),一切工作正常。但對於一個大的(也許使用類似refstreams的東西...來獲得最佳壓縮效果),拼寫頁面將作爲一個頁面打開,但其大小等於pdf大小。我能做什麼?

+0

不幸的是,有問題的PDF文件需要分析。你能提供樣品嗎?我想到的一個原因是:在每個頁面中都有文檔引用文檔中的所有資源,也就是頁面本身不需要的文檔。在這種文件的情況下,你的代碼將把所有的資源與每一頁一起復制。 – mkl 2013-03-22 09:54:16

+0

您需要提供什麼示例?此代碼是合併代碼 - inputpath - pdf位置,outputpath - 拆分頁面的文件夾。你有什麼想法如何「脫鉤」資源和網頁? – NET 2013-03-22 10:01:30

+0

不是樣本*代碼*,而是首先需要分析的樣本* PDF文檔*。我提到的原因是一個可能的原因。無論其原因在你的情況下,我不知道。 – mkl 2013-03-22 10:08:19

回答

4

在文檔中Top_Gear_Magazine_2012_09.pdf的原因的情況下,確實是我提到的:所有的頁引用對象2 0 R作爲他們/資源,並反過來引用的所有圖像2 0 OBJ字典在PDF中。

要將該文檔拆分爲僅包含所需圖像的部分文檔,您應該首先找到哪些圖像屬於哪些頁面,然後爲所有頁面創建單個字典,以預處理文檔。

由於您已經在這種情況下使用iText,您還可以使用它來找出哪些圖像是哪些頁面所需的。使用iText parser包最初通過使用RenderListener實現的頁面逐頁解析PDF,該實現的RenderImage方法只是記住在當前頁面上使用哪些圖像對象。 (作爲一種特殊的扭曲,iText隱藏了所討論的圖像XObject的名稱;不過,您可以獲得間接對象,並且可以查詢其對象和世代號碼,以便進行下一步操作)。

第二步,您在PdfStamper中打開文檔並遍歷頁面。對於每個頁面,您檢索字典並複製該字典,但只複製那些引用其中一個圖像對象的XObject對象引用,這些對象的對象編號和生成在第一步中記錄在各個頁面上。最後,將縮小的副本設置爲相關頁面的字典。

由此產生的PDF應該分裂得很好。

PS iText郵件列表最近出現了一個類似的問題。 In that thread the solution recipe given here has been improved,避開隱藏X對象名稱造成的iText的困難,我現在提議進行干預,通過使用不同的ContentOperator的「做」,這裏的Java版本之前的名稱丟失:

class Do implements ContentOperator 
{ 
    public void invoke(PdfContentStreamProcessor processor, PdfLiteral operator, ArrayList<PdfObject> operands) throws IOException 
    { 
     PdfName xobjectName = (PdfName)operands.get(0); 
     names.add(xobjectName); 
    } 

    final List<PdfName> names = new ArrayList<PdfName>(); 
} 

此內容操作員只需收集使用的xobjects的名稱,即爲給定頁面保留的xobject資源。