【问题标题】:iTextSharp get Actions from Table Of Content PDF C#iTextSharp 从内容 PDF C# 中获取操作
【发布时间】:2018-11-24 14:18:45
【问题描述】:

我有一个带有目录的 PDF:

使用 iTextSharp.dll 我试图获取注释然后对这些注释执行操作。然后我想操纵/更改链接以指向另一个页面。例如,如果目录中的 第 1 章 指向第 5 页,我希望在单击链接时它指向第 2 页。由于某种原因,注释上的操作为空,因此我无法操作此数据。下面的代码有效,但始终提供空 action。我不明白为什么会这样。 重现有问题的pdf

  • 创建一个 3 页的 word 文档
  • 第 1 页为目录,第 2 页为第 1 章,第 3 页为第 2 章
  • 导出为 PDF
  • 拥有 PDF 后,目录应该是“可点击的”。

然后我希望能够操纵它点击的位置。谢谢。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using iTextSharp.text;
using iTextSharp.text.pdf;
using System.IO;
using System.Collections;

namespace PDFLinks
{
    class Program
    {
        //Folder that we are working in
        //private static readonly string WorkingFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "Hyperlinked PDFs");
        //Sample PDF
        private static readonly string BaseFile = Path.Combine("C:\\Temp", "TableOfContentsTest.pdf");
        //Final file
        private static readonly string OutputFile = Path.Combine("C:\\Temp", "NewFile.pdf");

        static void Main(string[] args)
        {
            //Setup some variables to be used later
            PdfReader R = default(PdfReader);
            int PageCount = 0;

            //Open our reader
            R = new PdfReader(BaseFile);
            //Get the page cont
            PageCount = R.NumberOfPages;
            Console.WriteLine("Page Count= " + PageCount);

            //Loop through each page
            //for (int i = 1; i <= PageCount; i++)
            //{
                //Get the current page
                PdfDictionary PageDictionary = R.GetPageN(1);
                //Get all of the annotations for the current page
                PdfArray Annots = PageDictionary.GetAsArray(PdfName.ANNOTS);
                //Make sure we have something
                if ((Annots == null) || (Annots.Length == 0))
                {
                    Console.WriteLine("nothing");
                }

                //Loop through each annotation
                if (Annots != null)
                {
                    Console.WriteLine("ANNOTS Not Null" + Annots[0]);
                    foreach (PdfObject A in Annots.ArrayList)
                    {
                        //Convert the itext-specific object as a generic PDF object
                        PdfDictionary AnnotationDictionary = (PdfDictionary)PdfReader.GetPdfObject(A);                    
                        //Make sure this annotation has a link
                        if (!AnnotationDictionary.Get(PdfName.SUBTYPE).Equals(PdfName.LINK))
                            continue;
                        //Make sure this annotation has an ACTION
                        if (AnnotationDictionary.Get(PdfName.A) == null)
                            continue;
                        if (AnnotationDictionary.Get(PdfName.A) != null) 
                        {
                            Console.WriteLine("ACTION Not Null");
                        }
                        //Get the ACTION for the current annotation
                        PdfDictionary AnnotationAction = AnnotationDictionary.GetAsDict(PdfName.A);

                        // Test if it is a URI action (There are tons of other types of actions,
                        // some of which might mimic URI, such as JavaScript,
                        // but those need to be handled seperately)
                        if (AnnotationAction.Get(PdfName.S).Equals(PdfName.URI))
                        {
                            PdfString Destination = AnnotationAction.GetAsString(PdfName.URI);
                            string url1 = Destination.ToString();
                        }
                    }
                }
           //}
        }
    }
}

【问题讨论】:

  • 与列出没有格式的步骤相比,提供一个可以立即重现问题的文件的链接会增加您的机会
  • 这发生在任何文件上。使用 TOC 创建一个单词并将其转换为 PDF。
  • 链接可以有 Destinatoons 而不是操作...
  • @mkl 请详细说明,能否提供到达目的地的路径?
  • @AlfonsoCaruana 由于很难在评论中详细说明,我在回答中这样做了,见下文。

标签: c# pdf itext tableofcontents


【解决方案1】:

目的地目的地

在您的 Link 注释中,您只查找 Aaction 条目,但也可能存在 Destination 条目,参见。 PDF 规范 ISO 32000-2:

一个 字典 (可选;PDF 1.1) 激活链接注释时应执行的操作(请参阅第 12.6 节“操作”)。

目的地 数组、名称或字节串 (可选;如果存在 A 条目则不允许) 激活注释时应显示的目的地(12.3.2,“目的地”)。

(ISO 32000-2 表 176 - 特定于链接注释的附加条目)

有多种类型的目的地,参见。 this answer,特别是那里的规范引用,但那里处理其中一些类型的代码也可能很有趣。

A操作

即使对于带有A动作的链接,您也只考虑a)第一个动作和b) URI 类型的操作。

多个动作

链接s可以触发一系列动作,后续动作从第一个动作引用,参见。规范

下一步 字典或数组 (可选;PDF 1.2) 在此字典表示的操作之后应执行的下一个操作或操作序列。该值可以是单个动作字典或应按顺序执行的动作字典数组;进一步讨论见注 1。

注意 1 动作字典的 Next 条目 (PDF 1.2) 允许将动作序列链接在一​​起。例如,用鼠标单击链接注释的效果可能是播放声音、跳转到新页面和启动电影。请注意,Next 条目不限于单个操作,而是可能包含一系列操作,每个操作又可能有自己的 Next 条目。因此,这些动作可能会形成一棵树,而不是一个简单的链表。

(ISO 32000-2 表 196 - 所有动作词典通用的条目)

正如注释中的示例所暗示的那样,跳转到新页面不一定是链接的第一个操作,因此对于您的任务,您应该明确检查您的 的所有操作链接

动作类型

统一资源标识符 (URI) 是一个字符串,用于标识(解析为)Internet 上的资源——通常是作为超文本链接目标的文件,尽管它也可能解析为查询或其他实体。 (URI 在Internet RFC 3986,统一资源标识符 (URI):通用语法中进行了描述。

URI 操作会导致 URI 被解析。

(ISO 32000-2,第 12.6.4.8 节 URI 操作)

因此,URI 操作不太可能在 PDF 的 TOC 中找到。您最好寻找 GoTo 操作。

执行操作将视图更改为指定的目标(页面、位置和放大倍数)。 “表 202 - 特定于转到操作的附加条目”显示特定于此类操作的操作字典条目。

注意在链接注释或大纲项目的 A 条目中指定转到操作(请参阅“表 176 - 特定于链接注释的附加条目”和“表 151 - 条目大纲项目字典") 与直接使用 Dest 条目指定目的地的效果相同。

(ISO 32000-2 第 12.6.4.2 节 Go-To 操作)

D 名称、字节串或数组 (必需) 要跳转到的目的地(参见 12.3.2,“目的地”)。

(ISO 32000-2 表 202 - 特定于首选操作的附加条目)

因此,在检查 GoTo 操作时,您最终必须处理与检查答案顶部讨论的直接链接目标时相同类型的目标规范。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-02-02
    • 2013-03-31
    • 2016-04-05
    • 1970-01-01
    • 1970-01-01
    • 2015-09-09
    • 2015-02-06
    相关资源
    最近更新 更多