以下是我如何拆分大型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大小。我该怎么办?
答案 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资源。