itext7 pdf与书签合并

Posted

技术标签:

【中文标题】itext7 pdf与书签合并【英文标题】:itext7 pdf merge with bookmarks 【发布时间】:2019-11-17 21:54:30 【问题描述】:

我正在尝试将两个 pdf src1 和 src2 与书签合并,我使用 itext7 来合并 pdf。 pdf 正确合并但书签无法正常工作,来自 scr1 pdf 的书签在合并文档中始终分别指向 scr2 pdf。

scr1 书签1 ==> 指向src2 书签1

dfDocument pdfDoc = new PdfDocument(new PdfWriter(DEST));
PdfMerger merger = new PdfMerger(pdfDoc);
PdfDocument srcDoc1 = new PdfDocument(new PdfReader(SRC1));
PdfOutline rootOutline = pdfDoc.getOutlines(false);
PdfOutline srcOutline = srcDoc1.getOutlines(false);

PdfDocument srcDoc2 = new PdfDocument(new PdfReader(SRC2));
merger.merge(srcDoc1, 1, srcDoc1.getNumberOfPages());
merger.merge(srcDoc2, 1, srcDoc2.getNumberOfPages());

merger.close();
srcDoc1.close();
srcDoc2.close();
pdfDoc.close();

源 1 pdf 的书签始终指向源 2 pdf,源 2 pdf 书签在合并的 pdf 文档中正常工作。

请任何人帮我解决这个问题,我已经尝试了几种方法来重新指向目标并覆盖合并文档中的目标点,注意没有正确解决。

dfDocument pdfDoc = new PdfDocument(new PdfWriter(DEST));
PdfMerger merger = new PdfMerger(pdfDoc);
PdfDocument srcDoc1 = new PdfDocument(new PdfReader(SRC1));
PdfOutline rootOutline = pdfDoc.getOutlines(false);

PdfOutline srcOutline = srcDoc1.getOutlines(false);
PdfDocument srcDoc2 = new PdfDocument(new PdfReader(SRC2));

merger.merge(srcDoc1, 1, srcDoc1.getNumberOfPages());
merger.merge(srcDoc2, 1, srcDoc2.getNumberOfPages());

for(PdfOutline o : rootOutline.getAllChildren())       
    o.addDestination(PdfDestination.makeDestination(new PdfString(o.getTitle().toString())));


merger.close();
srcDoc1.close();
srcDoc2.close();
pdfDoc.close();

【问题讨论】:

【参考方案1】:

解决方案在合并前将目的地重命名为唯一的目的地后可以正常工作

PdfDocument srcDoc1 = new PdfDocument(new PdfReader(SRC1));
PdfDocument srcDoc2 = new PdfDocument(new PdfReader(SRC2));
PdfDocument srcDoc3 = new PdfDocument(new PdfReader(SRC3));

renameDest(srcDoc1);
renameDest(srcDoc2);
renameDest(srcDoc3);

merger.merge(srcDoc1, 1, srcDoc1.getNumberOfPages());
merger.merge(srcDoc2, 1, srcDoc2.getNumberOfPages());
merger.merge(srcDoc3, 1, srcDoc3.getNumberOfPages());

merger.close();
srcDoc1.close();
srcDoc2.close();
srcDoc3.close();
pdfDoc.close();

// 方法:重命名目的地

public static void renameDest(PdfDocument pdf) 

    try 
        String prefix = "cus-" + (index++) + "-";
        PdfNameTree destsTree = pdf.getCatalog().getNameTree(PdfName.Dests);
        PdfNameTree newNameTree = new PdfNameTree(pdf.getCatalog(), PdfName.Dests);
        for (Map.Entry<String, PdfObject> entry : destsTree.getNames().entrySet()) 
            newNameTree.addEntry(prefix + entry.getKey(), entry.getValue());
        

        for (Map.Entry<String, PdfObject> entry : newNameTree.getNames().entrySet()) 
            destsTree.addEntry(prefix + entry.getKey(), entry.getValue());
            System.out.println(entry.getKey() +"==>>"+ entry.getValue());
        

        PdfOutline rootOutline = pdf.getOutlines(false);
        updateOutlines(rootOutline, prefix);
     catch (Exception e) 
        e.printStackTrace();
    


//方法:更新大纲

public static void updateOutlines(PdfOutline parentOutline, String prefix) 
    for (PdfOutline outline : parentOutline.getAllChildren()) 
        updateOutlines(outline, prefix);
    
    if (parentOutline.getDestination() instanceof PdfStringDestination) 
        parentOutline.addDestination(new PdfStringDestination(prefix + ((PdfString) parentOutline.getDestination().getPdfObject()).getValue()));
    

【讨论】:

【参考方案2】:

这听起来非常像一个错误。

IIRC,书签可以使用几种不同的格式...它们可能只是“第 7 页”,或“此页面对象上的此查看区域,无论它碰巧是哪个页码”,以及介于两者之间的一些内容.

您的解决方案:

1) 为自己获取一份 PDF 规范的副本(大概是 Adob​​e 仍然托管它,尽管我已经有近 10 年没有需要查看它了。

2) 查看“书签”和“目的地”部分。

3) 当您导入任何 PDF 时,请检查其书签,并确保所有目的地都是“页面对象”类型。您可能必须“手动”转换它们,或者 iText 可能会将其作为一项功能提供。自从我从事 iText 工作以来已经有很长时间了,不知道从那时起他们在做什么。

顺便说一句,页面链接也可以是目的地...所以那些方便的目录和词汇表链接都可能被破坏。

您需要使用基本的对象级 PDF 操作器...PdfString、PdfDictionary、PdfArray 等...我建议使用 iText-RUPS。它使您可以在该基本对象级别查看 PDF,因此您可以查看其中的内容和要匹配的代码。有很多这样的程序在流传,但这是我脑海中唯一记得的一个。

【讨论】:

以上是关于itext7 pdf与书签合并的主要内容,如果未能解决你的问题,请参考以下文章

使用Python批量合并PDF文件(带书签功能)

python合并pdf并添加书签

Python 处理PDF文件 给PDF文件添加书签合并PDF文件转化PPT文件为PDF文件

应用 —— Python 处理PDF文件 给PDF文件添加书签合并PDF文件转化PPT文件为PDF文件

应用 —— Python 处理PDF文件 给PDF文件添加书签合并PDF文件转化PPT文件为PDF文件

iText7高级教程之构建基础块——6.创建动作(Action)目标(destinations)和书签(bookmarks)