如何获取PDF文件中链接的目标页面?

时间:2018-03-19 18:50:28

标签: java itext

使用iText,我们可以轻松更改链接的缩放级别。甚至有一块codeGoTo目的地类型执行此操作。如需便利,请在下面找到。

PdfReader reader = new PdfReader(src);
        PdfDictionary page = reader.getPageN(11);
        PdfArray annots = page.getAsArray(PdfName.ANNOTS); 
        for (int i = 0; i < annots.size(); i++) {
            PdfDictionary annotation = annots.getAsDict(i);
            if (PdfName.LINK.equals(annotation.getAsName(PdfName.SUBTYPE))) {
                PdfArray d = annotation.getAsArray(PdfName.DEST);
                if (d != null && d.size() == 5 && PdfName.XYZ.equals(d.getAsName(1)))
                    d.set(4, new PdfNumber(0));
            }
        }

该代码仅处理PDF文件中找到的目标类型之一。我有兴趣在其他类型的目的地中更改缩放(如果有人想知道,它们会在32000-1中列出)。具体来说,我想将每个目的地更改为GoTo类型并指定我自己的坐标。我希望左坐标与要跳转的页面的页面高度相同。要做到这一点,我显然需要页码。我怎么得到它?

到目前为止我做了什么? 指令PdfArray d = annotation.getAsArray(PdfName.DEST)给出了一个数组,其第一个(基于0)元素是页面引用,而不是页面编号,因为Bruno Lowagie在他的iText in Action, 2nd edition, p. 202). The array looks like this: [1931 0 R,/ XYZ,0,677,0中解释]`。我无法找到正确的命令来获取我自己的页码。因此,这篇文章。

2 个答案:

答案 0 :(得分:3)

According to this: https://developers.itextpdf.com/fr/node/1750

The first example is an array with two elements 8 0 R and /Fit. The second example is an array with four elements 6 0 R, /XYZ, 0, 806 and 0. You need the first element. It doesn't give you the page number (because there is no such thing as page numbers), but it gives you a reference to the /Page object. Based on that reference, you can deduce the page number by looping over the page tree and comparing the object number of a specific page with the object number in the destination.

And than you can go recursively to extract page number, like this: Extract page number from PDF file

Hope, you find it's helpful. Good luck!

答案 1 :(得分:2)

  

我希望左坐标与要跳转的页面的页面高度相同。要做到这一点,我显然需要页码。我怎么得到它?

您需要页码的假设是错误的。 PdfReader实用程序方法主要基于页码工作,是的,但这些方法并不多。因此,如果您对某些低级数据访问没问题,则不需要页码。

以下是您的代码,其中包含用于检索裁剪框(定义左,底,右和首页坐标)的附加代码,一次直接来自目标中的对象引用,一次通过页码。

PdfReader reader = new PdfReader(src);
PdfDictionary page = reader.getPageN(11);
PdfArray annots = page.getAsArray(PdfName.ANNOTS); 
for (int i = 0; i < annots.size(); i++) {
    PdfDictionary annotation = annots.getAsDict(i);
    if (PdfName.LINK.equals(annotation.getAsName(PdfName.SUBTYPE))) {
        PdfArray d = annotation.getAsArray(PdfName.DEST);
        if (d == null) {  // in case the link has not a Dest but instead a GoTo action
            PdfDictionary action = annotation.getAsDict(PdfName.A);
            if (action != null)
                d = action.getAsArray(PdfName.D);
        }

        if (d != null && d.size() > 0) {
            System.out.println("Next destination -");
            PdfIndirectReference pageReference = d.getAsIndirectObject(0);

            // Work with target dictionary directly
            PdfDictionary pageDict = d.getAsDict(0);
            PdfArray boxArray = pageDict.getAsArray(PdfName.CROPBOX);
            if (boxArray == null) {
                boxArray = pageDict.getAsArray(PdfName.MEDIABOX);
            }
            Rectangle box = PdfReader.getNormalizedRectangle(boxArray);
            System.out.printf("* Target page object %s has cropbox %s\n", pageReference, box);

            // Work via page number
            for (int pageNr = 1; pageNr <= reader.getNumberOfPages(); pageNr++) {
                PRIndirectReference pp = reader.getPageOrigRef(pageNr);
                if (pp.getGeneration() == pageReference.getGeneration() && pp.getNumber() == pageReference.getNumber()) {
                    System.out.printf("* Target page %s has cropbox %s\n", pageNr, reader.getCropBox(pageNr));
                    break;
                }
            }
        }
    }
}

ProcessLink test testDetermineTargetPage

顺便说一句,目的地也可以是命名目的地。因此,如果某些PDF的 Dest 值恰好不是数组而是字符串,则只需在 Dests 名称树中查找。< / p>