iTextSharp插入图像按钮字段不工作

iTextSharp插入图像按钮字段不工作,itext,Itext,我找了又找,找不到我问题的答案。我在我的代码中尝试了许多不同的方法,但我遇到了困难,我不知道从这里可以走到哪里。我似乎想做与这两条线相同的事情: 他们非常相似,答案是一样的。然而,当我使用这个精确的代码时,结果是一个没有图像的PDF。这是我的密码: using (var existingFileStream = new FileStream(fileNameExisting, FileMode.Open)) using (var newFileStream = new FileStrea

我找了又找,找不到我问题的答案。我在我的代码中尝试了许多不同的方法,但我遇到了困难,我不知道从这里可以走到哪里。我似乎想做与这两条线相同的事情:

他们非常相似,答案是一样的。然而,当我使用这个精确的代码时,结果是一个没有图像的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字段并获取字段类型时,该字段实际上是一个按钮字段。如果我在Adobe Reader中打开PDF并单击图像的占位符,它允许我从电脑中选择一个文件。当我将图像放入文件中,保存,然后读取该PDF时,我可以将代码更改为:

imageField.ProportionalIcon = false;
现在,图像突然在保存的副本上拉伸。所以我看到它正在改变这一部分,但这是当我在AdobeReader中手动输入图像时。当我在AdobeReader中设置图像并正确显示后在字段中阅读时,我看到了一些有趣的事情。field.Image属性为NULL,field.IconReference不为NULL。当我使用原始代码尝试插入图像时,它是反向的,其中图像不是NULL,但IconReference是NULL

任何帮助都将不胜感激,谢谢

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


这里有几件事在起作用

使用权:

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

您可以在此处使用RUP看到这一点(在屏幕截图中,您没有深入到足够的深度):

这有两个含义:

  • 签名解锁Adobe Reader中的特殊权限,例如在本地保存已填写表单的权限
  • 对原始PDF进行任何更改都会破坏签名并删除导致Adobe Reader中出现错误消息的特殊权限
此功能在PDF 2.0中已被弃用(甚至已从中删除)。随着AdobeReader以外的PDF查看器的出现,这项古老的技术已经过时

我的建议是:删除使用权以避免破坏签名。请参阅常见问题解答条目“为什么我会收到一个错误,说“扩展功能的使用不再可用”?/

这是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
条目,您会看到:

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

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

XFA在PDF 2.0中已被弃用,因为支持该技术的供应商不多。面对使用不推荐的技术的表单是一件令人沮丧的事情

我的建议:我将删除XFA部件。请参阅常见问题解答条目“删除XFA安全吗?”/

在iText 5中,删除XFA的操作如下:

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

重要提示:我的建议是从PDF中删除所有不推荐的功能,但如果政府希望该功能出现,那么你就倒霉了。在这种情况下,您需要使用Adobe软件来处理表单。如果是这样,你可以向政府抱怨,他们的要求导致了事实上的供应商锁定。顺便说一下:iText软件也是一家供应商。这是一家开源公司,根据AGPL许可证提供开源软件。AGPL许可证允许在某些情况下免费使用(请参阅)。如果您不满足这些要求,您必须购买商业许可证才能使用iText。

您确定您的表单是AcroForm吗?查看字段的名称(
form1[0].ec_Bldg_Photo_1[0].ImageField2[0]
),我发誓这是一个XFA表单。如果它是XFA表单,您不应该期望AcroForm代码工作。XFA在PDF 2.0(即ISO-32000-2)中已被弃用,因为所有人都撞到了您刚刚撞到的墙。弃用意味着不再支持它。如果仍然需要解决此问题,您可能希望获得iText支持。顺便说一句,你也在使用一个过时的iText版本,自愿支持已经停止。哇,谢谢你,布鲁诺,很抱歉我对PDF开发有点陌生,所以我不确定它是否是XFA。我有一个客户寄给我,希望我自动填写。有没有简单的检查方法?如果是XFA,获取其AcroForm版本的最佳方法是什么?是否可以使用Acrobat的专业版进行转换?最后,我认为我使用的是最新的支持iTextSharp for C#的iText。也许我误解了这个网站。我猜如果我不更新到版本7,我可能会遇到麻烦?非常感谢。我以为我使用的是最新的iText,它支持C#的iTextSharp。官方网站并不是这么说的:至于检查一个文件是纯XFA文件、混合XFA文件还是纯AcroForm文件,最好的方法是用(给我们一个屏幕截图,显示一下
/AcroForm
键下的内容)查看PDF文件。哦,好的,是的,我明白我的困惑所在。我认为我必须使用iTextSharp,它最多有5个,但iText是它的新名称:)我认为iText是不同的,显然很困惑!好的,非常感谢你,布鲁诺,我来看看