C# 将PDF中的外部链接转换为iTextSharp中嵌入附件的链接

C# 将PDF中的外部链接转换为iTextSharp中嵌入附件的链接,c#,itext,pdf-generation,C#,Itext,Pdf Generation,我的任务有点奇怪。我们即将关闭一个相当大的内部解决方案,并希望一次性导出它所持有的数据 该解决方案生成PDF格式的报告。这些PDF大多包含文本,但也包含图像。图像是激活后打开浏览器并指向图像完整版本的链接 由于我们将要关闭底层系统,到全尺寸图像的外部链接也将停止工作 出于各种奇怪的原因,我们对报告生成本身的控制有限,因此我们主要局限于报告的后处理 到目前为止,我设计的计划是从系统生成所有必要的报告,并通过iTextSharp进行处理。“所有”我试图实现的是处理每一份PDF,并且: 搜索外部链接

我的任务有点奇怪。我们即将关闭一个相当大的内部解决方案,并希望一次性导出它所持有的数据

该解决方案生成PDF格式的报告。这些PDF大多包含文本,但也包含图像。图像是激活后打开浏览器并指向图像完整版本的链接

由于我们将要关闭底层系统,到全尺寸图像的外部链接也将停止工作

出于各种奇怪的原因,我们对报告生成本身的控制有限,因此我们主要局限于报告的后处理

到目前为止,我设计的计划是从系统生成所有必要的报告,并通过iTextSharp进行处理。“所有”我试图实现的是处理每一份PDF,并且:

  • 搜索外部链接
  • 下载链接指向的全尺寸图像,并将其作为嵌入文件附加到PDF
  • 删除原始外部链接,并将其替换为指向相关嵌入式资源的链接
  • 我不熟悉PDF的底层结构,因此在尝试使用iTextSharp时遇到了不少麻烦。然而,到目前为止,我已经设法(1)和(2)整理好了。但我正在努力解决(3):

    我主要用它作为我的支持文档,但我还没有完全达到我的目标

    这是我处理每个注释的代码。请注意,我正在使用iTextSharp 5.5.13版:

    if (AnnotationDictionary.Get(PdfName.A) != null)
    {
        var annotActionObject = AnnotationDictionary.Get(PdfName.A);
        var AnnotationAction = (PdfDictionary)(annotActionObject.IsIndirect() ? PdfReader.GetPdfObject(annotActionObject) : annotActionObject);
    
        var type = AnnotationAction.Get(PdfName.S);
        //Test if it is a URI action
        if (type.Equals(PdfName.URI))
        {
            //Attach the downloaded file
            PdfFileSpecification pfs = PdfFileSpecification.FileEmbedded(writer, embFile.Path, embFile.Description, null);
            pfs.AddDescription(embFile.Description, false);
            writer.AddFileAttachment(pfs);
    
            //Removing old annotation
            AnnotationAction.Remove(PdfName.A);
            AnnotationDictionary.Remove(PdfName.A);
    
            PdfDestination destination = new PdfDestination(PdfDestination.FIT);
            destination.AddFirst(new PdfNumber(1));
    
            var target = new PdfTargetDictionary(true);
            target.EmbeddedFileName = embFile.Name;
    
            PdfAction action = PdfAction.GotoEmbedded(null, target, destination, true);
    
            AnnotationDictionary.Put(PdfName.D, action.Get(PdfName.D));
            AnnotationAction.Put(PdfName.D, action.Get(PdfName.D));
        }
    }
    
    对某些人来说,这很可能相当明显,为什么它不起作用:)

    现在,一切正常,它在另一端吐出一个PDF。如前所述,PDF中的图像不再具有活动链接,所有附加文件都按预期嵌入。然而,到嵌入式资源的链接不起作用,而且任何地方都没有它的迹象


    非常感谢所有反馈。谢谢。

    如评论中所述,您只能链接到嵌入的PDF文件

    您只需更改
    D
    项。您需要覆盖整个
    A
    条目,但请确保保留目标的位置

    下面是我创建的一个快速POC:

    PdfReader reader = new PdfReader(INPUT_FILE);
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(OUTPUT_FILE));
    
        PdfFileSpecification fs = PdfFileSpecification.fileEmbedded(stamper.getWriter(), null, "EmbeddedFile.pdf", FileUtils.readFileToByteArray(new File(INPUT_FOLDER + "embeddedfile.pdf")));
        fs.addDescription("specificname", false);
        stamper.getWriter().addFileAttachment(fs);
        PdfTargetDictionary targetDictionary = new PdfTargetDictionary(true);
        targetDictionary.setEmbeddedFileName("specificname");
    
    
        PdfDestination dest = new PdfDestination(PdfDestination.FIT);
        dest.addFirst(new PdfNumber(1));
        PdfAction action = PdfAction.gotoEmbedded(null, targetDictionary, dest, true);
    
        PdfDictionary page = reader.getPageN(1);
        PdfArray annotations = page.getAsArray(PdfName.ANNOTS);
    
    
        for(int x=0;x<annotations.size();x++) {
            PdfDictionary annotation = annotations.getAsDict(x);
            PdfArray location = annotation.getAsArray(PdfName.RECT);
            action.put(PdfName.RECT,location);
            annotation.put(PdfName.A, action);
        }
    
    
        stamper.close();
    
    PdfReader reader=新的PdfReader(输入_文件);
    PdfStamper stamper=新PdfStamper(读取器,新文件输出流(输出文件));
    PdfFileSpecification fs=PdfFileSpecification.fileEmbedded(stamper.getWriter(),null,“EmbeddedFile.pdf”,FileUtils.readFileToByteArray(新文件(输入文件夹+“EmbeddedFile.pdf”));
    fs.addDescription(“具体名称”,假);
    stamper.getWriter().addFileAttachment(fs);
    PdfTargetDictionary targetDictionary=新的PdfTargetDictionary(true);
    setEmbeddedFileName(“specificname”);
    PDFDestimation dest=新的PDFDestimation(PDFDestimation.FIT);
    目的地地址第一(新的PDFN编号(1));
    PdAction=PdAction.gotoEmbedded(null,targetDictionary,dest,true);
    PdfDictionary page=reader.getPageN(1);
    PdfArray annotations=page.getAsArray(PdfName.ANNOTS);
    
    对于(int x=0;x),很遗憾,这是一个无法满足的要求。请参阅和PDF规范的相关章节。通过
    goToEmbedded()
    方法创建的GoTo操作只能有效地打开嵌入的PDF文件。最新版本的PDF规范ISO 32000-2甚至使其更为明确:“注意:嵌入到操作仅适用于PDF类型的文件"。其他文件格式,很可能是出于安全考虑,无法通过该操作打开。@JonReilly,谢谢你。我最近在其他地方遇到了这些详细信息。我只是尝试添加PDF而不是图像。不幸的是,我的操作仍然不起作用。Acrobat Reader中没有抛出错误或警告,因此我没有真正执行此操作有什么可以遵循的吗?你精通iTextSharp来评论我的代码吗?理论上,因为我为iText=P工作。我将添加一个快速的答案。非常感谢!经过一些调整,我成功地让它在我的应用程序中工作。现在,这只是一个关于下一步的内部讨论。再次,非常感谢你为我们精心设计的答案和样本。