iTextSharp插入图像PushbuttonField无法正常工作

时间:2017-12-12 22:24:57

标签: itext

我搜索过并找不到问题的答案。我已经在我的代码中尝试了许多不同的方法,但我已经碰壁了,我不确定从哪里开始。我似乎想要做与这两个线程相同的事情:

Trying to insert an image into a pdf‏ in c#

Add image in an existing PDF with itextsharp

它们非常相似,答案是一样的。但是,当我使用该确切代码时,结果是没有图像的PDF。这是我的代码:

using (var existingFileStream = new FileStream(fileNameExisting, FileMode.Open))
  using (var newFileStream = new FileStream(fileNameNew, FileMode.Create))
   {
    var pdfReader = new PdfReader(existingFileStream);

    var stamper = new PdfStamper(pdfReader, newFileStream, '\0', true);

    var form = stamper.AcroFields;
    var fieldKeys = form.Fields.Keys;

    foreach (var field in form.Fields)
    {
       if (field.Key == "form1[0].ec_Bldg_Photo_1[0].ImageField2[0]")
       {
          PushbuttonField imageField = form.GetNewPushbuttonFromField(field.Key);
          imageField.Layout = PushbuttonField.LAYOUT_ICON_ONLY;
          imageField.IconReference = null;
          imageField.ProportionalIcon = true;
          imageField.Image = Image.GetInstance(@"PATH_TO_IMAGE\front.jpg");
          form.ReplacePushbuttonField(field.Key, imageField.Field);
       }
    }
    stamper.FormFlattening = false;

    stamper.Close();
    pdfReader.Close();
}

我试图排除所有显而易见的事情。我的图像路径是正确的,当我读取现有的PDF字段并获取字段类型时,该字段确实是一个PushbuttonField。如果我在Adobe Reader中打开PDF并单击图像的占位符,它允许我从我的PC中选择一个文件。当我将图像放入文件,保存,然后读取该PDF时,我可以将我的代码更改为:

imageField.ProportionalIcon = false;

现在突然间,图像在保存的副本上被拉伸。所以我看到它正在改变这部分,但这是我在Adobe Reader中手动输入图像的时候。在我在Adobe Reader中设置该图像并且显示正确后,我在该领域阅读时,我看到了一些有趣的事情。 field.Image属性为IS NULL,field.IconReference为NOT NULL。当我使用原始代码尝试插入图像时,它是相反的,其中Image为NOT NULL但IconReference为空

非常感谢任何帮助,谢谢!!

编辑1:好的,所以我第一次没有看到它,但我回去检查得更彻底,我确实找到了钥匙。这是:

enter image description here

1 个答案:

答案 0 :(得分:1)

这里有几件事情在发挥作用。

使用权利

PDF使用Adobe拥有的私钥进行数字签名。

你可以在这里使用RUPS看到这一点(在屏幕截图中你没有足够):

enter image description here

这有两个含义:

  • 签名解锁Adobe Reader中的特殊权限,例如在本地保存已填写表单的权限。
  • 对原始PDF进行任何更改会破坏签名并删除特殊权限,从而导致Adobe Reader中出现难看的错误消息。

此功能已弃用(甚至已删除)PDF 2.0。随着Adobe Reader以外的PDF查看器的出现,它的旧技术已经过时。

我的建议:删除使用权限以避免破坏签名。请参阅常见问题解答条目"为什么我会收到错误消息,说明"扩展功能的使用已不再可用"?" iText 7 / iText 5

这是iText 7代码:

public void removeUsageRights(PdfDocument pdfDoc) {
    PdfDictionary perms = pdfDoc.getCatalog().getPdfObject().getAsDictionary(PdfName.Perms);
    if (perms == null) {
        return;
    }
    perms.remove(new PdfName("UR"));
    perms.remove(PdfName.UR3);
    if (perms.size() == 0) {
        pdfDoc.getCatalog().remove(PdfName.Perms);
    }
}

这是iText 5代码:

PdfReader reader = new PdfReader(old_file);
if (reader.hasUsageRights()) {
    reader.removeUsageRights();
    PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(new_file));
    stamper.close();
}
reader.close();

这是iText 5的答案。

混合形式:

如果单击/AcroForm条目,您会看到:

enter image description here

有一个/Fields数组,其中包含对字段字典的引用,这些字典也是窗口小部件注释。这意味着该文档内部有一个AcroForm表单。但是,还有一个带有一系列XML片段的/XFA条目。这意味着该文档内部有一个XFA表单。

换句话说:在内部添加两次相同的表单描述。您正在更改一个表单中的按钮(AcroForm部分),但不会更改另一个表单(XFA表单),这会导致不一致。

XFA已在PDF 2.0中弃用,因为没有多家供应商支持该技术。面对使用弃用技术的表单会感到沮丧。

我的建议:我会删除XFA部分。请参阅常见问题条目"删除XFA是否安全?" iText 5 / iText 7

在iText 5中,删除XFA的方式如下:

AcroFields form = stamper.getAcroFields();
form.removeXfa();

重要提示:我的建议是从PDF中删除所有已弃用的功能,但如果政府希望该功能存在,那么您运气不好。在这种情况下,您将需要使用Adobe软件来处理表单。如果是这种情况,你可以向政府抱怨他们的要求会导致事实上的供应商锁定。顺便说一句:iText软件也是供应商。它是一家开源公司,根据AGPL许可证提供开源软件。 AGPL许可证允许在某些情况下免费使用(请参阅How do I make sure my software complies with AGPL: How can I use iText for free?)如果您不满足这些要求,则必须购买商业许可才能使用iText。