You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取PDF文档中内部跳转(GoTo动作)链接的目标页面及矩形区域?

如何获取PDF文档中内部跳转(GoTo动作)链接的目标页面及矩形区域?

嘿,你已经把基础工作做好了——成功定位到PDF页面上的Link注解,接下来只需要解析它的GoTo动作就能拿到你要的目标页面和矩形信息啦。我来帮你把代码补全,还会给你讲清楚每一步的逻辑:

public static void GetLinks(PdfDocument pdfDocument, int page)
{
    // 获取目标页面上的所有注解
    IList<PdfAnnotation> annotations = pdfDocument.GetPage(page).GetAnnotations();
    
    // 遍历所有注解
    foreach (PdfAnnotation annotation in annotations)
    {
        // 筛选出Link类型的注解
        if (annotation.GetSubtype() == PdfName.Link)
        {
            PdfLinkAnnotation linkAnnotation = annotation as PdfLinkAnnotation;
            if (linkAnnotation == null) continue;
            
            // 获取该链接的动作
            PdfAction action = linkAnnotation.GetAction();
            if (action == null) continue;
            
            // 只处理内部跳转的GoTo动作(排除外部链接URI等其他类型)
            if (action.GetSubtype() == PdfName.GoTo)
            {
                // 获取GoTo动作的目标数组
                PdfArray destArray = action.Get(PdfName.D) as PdfArray;
                if (destArray == null || destArray.Count < 2) continue;
                
                // 解析目标页面:数组第一个元素是目标页的字典对象
                PdfDictionary targetPageDict = destArray.GetAsDictionary(0);
                int destinationPageNo = pdfDocument.GetPageNumber(targetPageDict);
                
                // 解析目标矩形/定位坐标:根据GoTo动作的不同目标类型处理
                float[] targetRect = null;
                PdfName destType = destArray.GetAsName(1);
                
                // 处理FitR类型:直接返回目标矩形的四个坐标(左、下、右、上)
                if (destType == PdfName.FitR)
                {
                    if (destArray.Count >= 6)
                    {
                        targetRect = new float[]
                        {
                            destArray.GetAsNumber(2).FloatValue,
                            destArray.GetAsNumber(3).FloatValue,
                            destArray.GetAsNumber(4).FloatValue,
                            destArray.GetAsNumber(5).FloatValue
                        };
                    }
                }
                // 处理XYZ类型:返回锚点坐标(x,y),可以结合页面尺寸生成默认矩形
                else if (destType == PdfName.XYZ)
                {
                    float x = destArray.GetAsNumber(2).FloatValue;
                    float y = destArray.GetAsNumber(3).FloatValue;
                    // 这里可以自定义矩形的宽高,比如取50x50的区域
                    targetRect = new float[] { x, y - 25, x + 50, y + 25 };
                }
                // 其他类型比如Fit、FitH等可以根据需求补充处理
                else
                {
                    // 如果是Fit(适配整页),目标矩形就是整个页面的尺寸
                    PdfPage targetPage = pdfDocument.GetPage(destinationPageNo);
                    Rectangle pageSize = targetPage.GetPageSize();
                    targetRect = new float[] { pageSize.GetLeft(), pageSize.GetBottom(), pageSize.GetRight(), pageSize.GetTop() };
                }
                
                // 现在你可以使用拿到的信息了
                Console.WriteLine($"源矩形: {annotation.GetRectangle()}");
                Console.WriteLine($"目标页码: {destinationPageNo}");
                if (targetRect != null)
                {
                    Console.WriteLine($"目标矩形: 左={targetRect[0]}, 下={targetRect[1]}, 右={targetRect[2]}, 上={targetRect[3]}");
                }
            }
        }
    }
}

一些需要注意的细节:

  • 不是所有Link注解都是内部跳转:有些是外部链接(PdfName.URI类型的动作),所以一定要先判断动作子类型是PdfName.GoTo
  • GoTo动作的目标格式有多种:PDF规范里定义了Fit、FitH、FitV、FitR、XYZ等多种视图模式,上面的代码覆盖了最常见的几种,你可以根据自己的需求扩展其他类型
  • 目标页的解析:PDF里的目标页通常是用页字典对象存储的,通过pdfDocument.GetPageNumber()可以把字典转换成我们熟悉的页码
  • 坐标系统:PDF的坐标原点在页面左下角,和我们日常的屏幕坐标(左上角为原点)不一样,处理的时候要注意转换

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.07 12:58:02