这是我分割大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之类的东西进行更好的压缩),拆分页面将以一页打开,但其大小等于原始PDF的大小。我该怎么办?
对于您的文档Top_Gear_Magazine_2012_09.pdf,确实是我提到的原因:所有页面都将对象2 0 R称为/ Resources,而字典将2 0 obj]引用>依次引用PDF中的所有图像。
要将该文档分成仅包含所需图像的部分文档,您应先查找哪些图像属于哪些页面,然后为所有页面创建单独的/ Resources
词典,对文档进行预处理。由于您已经在这种情况下使用了iText,因此您也可以使用它来查找哪些页面需要哪些图像。使用iText parser
程序包通过RenderListener
实现对其页面进行最初的PDF解析,该实现的RenderImage
方法仅记住当前页面上使用了哪些图像对象。 (作为一种特殊的用法,iText隐藏了所讨论的图像XObject的名称;不过,您获得了间接对象,并且可以查询其对象和世代号,足以进行下一步。)
[第二步,在PdfStamper
中打开文档,然后遍历页面。对于每个页面,您都检索/ Resources
生成的PDF应该可以很好地分割。
PS
最近,iText邮件列表中出现了一个非常类似的问题。 In that thread the solution recipe given here has been improved,要解决因iText隐藏xobject名称而造成的困难,我现在建议通过使用不同的ContentOperator
作为“ Do”(在此为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>(); }
此内容运算符仅收集使用的xobject的名称,即为给定页面保留的xobject资源。