如何使用iTextSharp在pdf文件中获取部分目标页码?

时间:2012-04-25 12:38:52

标签: asp.net pdf annotations itextsharp

我有一个pdf文件,其中包含索引页面,其中包含带有目标页面的部分。 我可以得到部分名称(第1.1节,第5.2节)但我无法获得目标页码......

对于前: http://www.mikesdotnetting.com/Article/84/iTextSharp-Links-and-Bookmarks

这是我的代码:

string FileName = AppDomain.CurrentDomain.BaseDirectory + "TestPDF.pdf";
PdfReader pdfreader = new PdfReader(FileName);
PdfDictionary PageDictionary = pdfreader.GetPageN(9);
PdfArray Annots = PageDictionary.GetAsArray(PdfName.ANNOTS);       
if ((Annots == null) || (Annots.Length == 0))
    return;

foreach (PdfObject oAnnot in Annots.ArrayList)
{
    PdfDictionary AnnotationDictionary = (PdfDictionary)PdfReader.GetPdfObject(oAnnot);          

    if (AnnotationDictionary.Keys.Contains(PdfName.A))
    {
        PdfDictionary oALink = AnnotationDictionary.GetAsDict(PdfName.A);

        if (oALink.Get(PdfName.S).Equals(PdfName.GOTO))
        {
            if (oALink.Keys.Contains(PdfName.D))
            {
                PdfObject objs = oALink.Get(PdfName.D);
                if (objs.IsString())
                {
                    string SectionName = objs.ToString(); // here i could see the section name...
                }
            }
        }
    }
}

如何获取目标页码?

我也无法访问某些pdf ex的部分名称:http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/pdf/pdfs/adobe_supplement_iso32000.pdf

在这个PDF第9页包含一个我无法获得该部分的部分。 所以请给我解决方案......

1 个答案:

答案 0 :(得分:3)

有两种可能的链接注释类型,ADestA是更强大的类型,但通常是矫枉过正。 Dest类型仅指定对页面的间接引用以及一些拟合和缩放选项。

Dest值可以是几个不同的东西,但通常(据我所知)一个命名字符串目的地。您可以在文档的名称目标字典中查找命名目标。所以在你的主循环之前添加它以便以后可以引用它:

//Get all existing named destinations
Dictionary<string, PdfObject> dests = pdfreader.GetNamedDestinationFromStrings();

一旦你将Dest作为字符串,就可以将该对象看作上述字典中的一个键。

PdfArray thisDest = (PdfArray)dests[AnnotationDictionary.GetAsString(PdfName.DEST).ToString()];

返回的数组中的第一项是您习惯使用的间接引用。 (实际上,第一项可能是表示远程文档中页码的整数,因此您可能需要检查它。)

PdfIndirectReference a = (PdfIndirectReference)thisDest[0];
PdfObject thisPage = PdfReader.GetPdfObject(a);

下面是将大部分内容放在一起的代码,省略了您已经拥有的一些代码。 ADest根据规范是互斥的,因此任何注释都不应同时指定。

//Get all existing named desitnations
Dictionary<string, PdfObject> dests = pdfreader.GetNamedDestinationFromStrings();

foreach (PdfObject oAnnot in Annots.ArrayList) {
    PdfDictionary AnnotationDictionary = (PdfDictionary)PdfReader.GetPdfObject(oAnnot);

    if (AnnotationDictionary.Get(PdfName.SUBTYPE).Equals(PdfName.LINK)) {
        if (AnnotationDictionary.Contains(PdfName.A)) {
            //...Do normal A stuff here
        } else if (AnnotationDictionary.Contains(PdfName.DEST)) {
            if (AnnotationDictionary.Get(PdfName.DEST).IsString()) {//Named-based destination
                if (dests.ContainsKey(AnnotationDictionary.GetAsString(PdfName.DEST).ToString())) {//See if it exists in the global name dictionary
                    PdfArray thisDest = (PdfArray)dests[AnnotationDictionary.GetAsString(PdfName.DEST).ToString()];//Get the destination
                    PdfIndirectReference a = (PdfIndirectReference)thisDest[0];//TODO, this could actually be an integer for the case of Remote Destinations
                    PdfObject thisPage = PdfReader.GetPdfObject(a);//Get the actual PDF object
                }
            } else if(AnnotationDictionary.Get(PdfName.DEST).IsArray()) {
                //Technically possible, I think the array matches the code directly above but I don't have a sample PDF
            }
        }
    }
}