【问题标题】:Creating Image Form Fields for PDFs in iText 7 .NET/C#在 iText 7 .NET/C# 中为 PDF 创建图像表单字段
【发布时间】:2020-05-17 07:21:34
【问题描述】:

我正在尝试在 PDF 中创建一个表单字段,用户可以在其中插入图像文件并保存文档,以便图像是持久的(在新的 PDF 文档中,而不是更改现有文档)。我知道这是可能的,因为我已经看到它在其他 PDF 中完成,但我无法弄清楚它应该如何在 iText 7 for .NET/C# 中完成。

我在 Google 上找到了this,它似乎至少提供了解决方案的 JavaScript 和大纲,但我不知道如何编辑 iText PdfButtonFormField 对象的“布局”。我也尝试过 iText 网站上的this answer,但它适用于添加到现有文档中,无论如何我都无法让它工作(一些更难以捉摸的System.NullReferenceException 错误)。

使用创建按钮和替换图像的想法,到目前为止我已经尝试过:

PdfWriter writer = new PdfWriter("myfile.pdf");
PdfDocument document = new PdfDocument(writer);
PdfPage pdfPage = document.AddNewPage(PageSize.A4);
PdfCanvas canvas = new PdfCanvas(pdfPage);

PdfAcroForm form = canvas.GetForm();

PdfButtonFormField button = PdfFormField.CreateButton(document, new Rectangle(50, 50), 0);

button.SetAction(PdfAction.CreateJavaScript("event.target.buttonImportIcon();"));

form.AddField(button); // <-- Error on this line

document.Close();
writer.Close();

希望buttonImportIcon() 足以覆盖按钮的外观。但我在指示的行收到System.NullReferenceException: 'Object reference not set to an instance of an object.' 错误(不幸的是,它没有比这更具体),堆栈跟踪有点无用:

Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object.
    at iText.Forms.PdfAcroForm.AddField(PdfFormField field, PdfPage page)
    at iText.Forms.PdfAcroForm.AddField(PdfFormField field)
    at ReplaceIcon.Main(String[] args) in ReplaceIcon.cs:line 65

我还尝试将CreateButton 替换为CreatePushButton,如下所示:

PdfButtonFormField button = PdfFormField.CreatePushButton(document, new Rectangle(50, 50), "name", "caption");

使用哪个代码编译,当我单击 PDF 中的按钮时,我得到一个“选择图像”对话框,但该按钮仍然只是一个灰色的正方形,上面写着“标题”,而不是被替换选择的图像。但我怀疑需要一个通用按钮,以便您可以覆盖布局(以某种方式)。

如果有人知道这应该如何完成,无论是使用此按钮方法还是其他方式,我都会非常感谢一些指针。正如我所说,我对在 C# 程序中使用 iText 7 在新生成的 PDF 文档中创建这些字段特别感兴趣。

【问题讨论】:

  • 当你点击那个空引用时你能分享堆栈跟踪吗?请edit回答您的问题。
  • 我已经包含了它,但我不确定它在这里有多大帮助 - 不幸的是,它是一个相当不透明的堆栈跟踪。至少,对我来说……我总是很可能会遗漏一些东西。
  • 你能试试form.AddField(button, pdfPage);看看效果如何。
  • 恐怕又是几乎完全相同的堆栈跟踪,只是缺少 at iText.Forms.PdfAcroForm.AddField(PdfFormField field) 行。
  • 好的,值得一试。恐怕这需要 itext 的追随者之一来解决。这可能与您要添加它的页面有关,主要是因为在 itext 库中引发了该空指针。

标签: c# pdf itext acrofields


【解决方案1】:

但我得到一个 System.NullReferenceException: 'Object reference not set to an instance of an object。'

这是 Acroform#addField 方法中的错误。每次获取无名字段作为参数时都会抛出 NPE。 为避免这种情况,只需在添加到表单之前设置字段名称 (field#setName)。

使用哪个代码编译,当我单击 PDF 中的按钮时,我得到一个“选择图像”对话框,但该按钮仍然只是一个灰色的正方形,上面写着“标题”,而不是被替换选择的图像。但我怀疑需要一个通用按钮,以便您可以覆盖布局(以某种方式)。

PdfFormField.CreateButton 方法在这里没有任何优势。 iText 中的该方法会创建一个空的 PdfButtonFormField(外观和行为应由开发人员在创建字段后定义)。

另一方面,CreatePushButton 几乎可以满足您的需求。 唯一必须调整的是布局。默认情况下,创建的按钮具有“仅标签”布局。

  public void Generate()
    {
        PdfWriter writer = new PdfWriter("myfile.pdf");
        PdfDocument document = new PdfDocument(writer);

        PdfAcroForm form = PdfAcroForm.GetAcroForm(document, true);
        PdfButtonFormField button = PdfFormField.CreatePushButton(document, new Rectangle(20, 500, 50, 50), "btn",
            "load");
        button.SetAction(PdfAction.CreateJavaScript("event.target.buttonImportIcon();"));
//change the layout type.   
PdfDictionary widget = (PdfDictionary) button.GetKids().Get(0).GetIndirectReference().GetRefersTo();
    widget.GetAsDictionary(PdfName.MK).Put(PdfName.TP, new PdfNumber((int) PushButtonLayouts.ICON_ONLY));

        form.AddField(button); // <-- Error on this line

        document.Close();
    }

    enum PushButtonLayouts
    {
        LABEL_ONLY = 0, //No icon; caption only
        ICON_ONLY = 1, //No caption; icon only
        ICON_TOP_LABEL_BOTTOM = 2, // Caption below the icon
        LABEL_TOP_ICON_BOTTOM = 3, // Caption above the icon
        ICON_LEFT_LABEL_RIGHT = 4, //Caption to the right of the icon
        LABEL_LEFT_ICON_RIGHT = 5, //Caption to the left of the icon
        LABEL_OVER = 6 // Caption overlaid directly on the icon
    }

【讨论】:

  • 啊,太棒了,谢谢。如果我可能会问后续问题(我不确定 StackOverflow 上关于此的礼仪,如果发错地方了,请致歉),您是否碰巧知道是否有办法在按钮上设置初始图像,而不仅仅是文本或空白?令人困惑的是,SetImage 函数只接受一个字符串,我不知道如何处理SetImageAsForm(PdfFormXObject form) 方法(因为我不知道如何将使用 ImageData 制作的 PdfXObject 转换为 PdfFormXObject)。
  • 其实setImage只是通过setValue()方法将Base64编码的图片设置为按钮值。
  • 恐怕你把我弄丢了。 SetValue() 和设置图标不一样吧?并且您可以将 ImageData 转换为 Base64 编码字符串,还是必须使用一些额外的机器?
  • 如果您查看 PdfButtonFormFIeld 类:github.com/itext/itext7-dotnet/blob/develop/itext/itext.forms/…,您会发现 setImage 方法在后台调用 setValue(第 198 行)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-05
  • 1970-01-01
  • 2016-06-08
  • 2012-06-28
  • 1970-01-01
  • 2017-06-12
相关资源
最近更新 更多