itextsharp:拆分页面大小等于文件大小

时间:2013-03-22 09:31:54

标签: c# itextsharp

以下是我如何拆分大型pdf(144 mb)

    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这样的东西......以获得最佳压缩),spliited页面打开为一页,但其大小等于pdf大小。我该怎么办?

1 个答案:

答案 0 :(得分:4)

如果您的文档Top_Gear_Magazine_2012_09.pdf确实是我提到的原因:所有网页都将对象 2 0 R 称为 / Resources ,并且 2 0 obj 中的字典依次引用PDF中的所有图像。

要将该文档拆分为仅包含所需图像的部分文档,您应首先找出哪些图像属于哪些页面然后为所有页面创建单独的 / Resources 词典来预处理文档。 / p>

由于您已在此上下文中使用iText,因此您还可以使用它来查找哪些页面需要哪些图像。使用iText parser包最初使用RenderListener实现逐页解析PDF,RenderImage方法只记住当前页面上使用的图像对象。 (作为一种特殊的转折,iText会隐藏所讨论的图像XObject的名称;但是,您可以获得间接对象,并且可以查询其对象和世代号,这对于下一步而言就足够了。)

在第二步中,您在PdfStamper中打开文档并遍历页面。对于每个页面,您检索 / Resources 字典并将其复制,但仅复制那些引用其中一个图像对象的XObjects引用,这些图像对象的对象编号和生成是您在第一步中记住的相应页面。最后,将缩小的副本设置为相关页面的 / Resources 字典。

生成的PDF应该分割得很好。

PS 最近在iText邮件列表上出现了一个非常类似的问题。 In that thread the solution recipe given here has been improved,为了解决iText隐藏xobject名称所带来的困难,我现在建议在名称丢失之前进行干预,使用不同的ContentOperator作为“Do”,这里是Java版本:< / p>

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资源。