2013-03-22 81 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资源。