我有一张带有TOC的PDF:
使用iTextSharp.dll我试图获取注释然后对这些注释进行操作。然后我想操纵/更改链接指向另一个页面。例如,如果TOC中的第1章指向第5页,我希望在点击链接时指向第2页。由于某种原因,对注释的操作为空,因此我无法操纵此数据。下面的代码有效但仍然提供空操作。我不明白为什么会这样。 重现有问题的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();
}
}
}
//}
}
}
}
答案 0 :(得分:2)
在链接注释中,您只需查找 A ction条目,但也可能是 Dest ination条目,参见PDF规范ISO 32000-2:
<强> A 强> 字典 (可选; PDF 1.1)激活链接注释时应执行的操作(参见12.6,&#34;操作&#34;)。
<强>目的地强> 数组,名称或字节字符串 (可选;如果存在 A 条目,则不允许)激活注释时应显示的目的地(12.3.2,&#34;目的地&#34; )。
(ISO 32000-2表176 - 特定于链接注释的附加条目)
有许多类型的目的地,参见this answer,特别是那里的规范引用,但处理其中一些类型的代码也可能是有意义的。
即使对于带有 A ctions的链接,您也只考虑 a) 第一个操作 b) URI 类型的操作。
链接可以触发一系列操作,后续操作从第一个操作引用,参见规范
下一步强> 字典或数组 (可选; PDF 1.2)在此词典表示的操作之后应执行的下一个操作或操作序列。值可以是单个动作字典,也可以是按顺序执行的动作字典数组;有关进一步讨论,请参阅注释1。
注1:动作词典的下一步条目(PDF 1.2)允许将一系列动作链接在一起。例如,使用鼠标单击链接注释的效果可能是播放声音,跳转到新页面以及启动电影。请注意,下一步条目不限于单个操作,但可能包含一系列操作,每个操作都可能包含自己的下一步条目。因此,动作可以形成树而不是简单的链接列表。
(ISO 32000-2表196 - 所有动作词典共有的条目)
正如NOTE中的示例所示,跳转到新页面不一定是链接的第一个操作,因此对于您的任务,您应该明确检查的所有操作链路强>
统一资源标识符(URI)是一个字符串,用于标识(解析)Internet上的资源 - 通常是作为超文本链接目标的文件,尽管它也可以解析为查询或其他实体。 (URI在 Internet RFC 3986,统一资源标识符(URI):通用语法。中描述)
URI 操作会导致URI被解析。
(ISO 32000-2,第12.6.4.8节“URI动作”)
因此, URI 操作不太可能在PDF的TOC中找到。您最好查找 GoTo 操作。
转到操作将视图更改为指定目标(页面,位置和放大系数)。 &#34;表202-特定于参与动作的附加条目&#34;显示特定于此类操作的操作字典条目。
注意在链接注释或大纲项目的 A 条目中指定定位操作(请参阅&#34;表176 - 特定于链接注释的附加条目&#34;和&# 34;表151 - 大纲项目词典中的条目&#34;)与使用 Dest 条目直接指定目的地具有相同的效果。
(ISO 32000-2第12.6.4.2节“转到操作”)
<强> d 强> 名称,字节字符串或数组 (必填)要跳转的目的地(见12.3.2,&#34;目的地&#34;)。
(ISO 32000-2表202 - 特定于实施行动的附加条目)
因此,在检查 GoTo 操作时,您最终必须处理与检查答案顶部讨论的直接链接目标时相同的目标规范。