代码之家  ›  专栏  ›  技术社区  ›  Aidal

PDF表单在部分填充后不再可编辑

  •  2
  • Aidal  · 技术社区  · 6 年前

    我遇到了一个Web API的问题,我有一个接收PDF文档(PDF表单)作为base64编码字符串,使它成为一个文件,填写一些字段(使用 iTextSharp公司 PdfStamper 类),并将结果作为base64编码字符串发送回,在该字符串中,它将再次生成一个文件。

    我仍然可以编辑字段,但是在尝试使用 ,字段不再可编辑。

    打开属性页并查看中文档的安全属性时 ,上面说什么都可以。

    我可以看到许多其他人都发表了类似的问题,但我没有看到我的具体问题在那里。

    有人知道这里发生了什么事,以及如何避开它吗?

    编辑:添加代码

    我正在这样做(稍微简化,但相同):

    PdfReader reader = new PdfReader("path to PDF form file");
    
    stamp = new PdfStamper(reader, new FileStream("path to filled PDF form file", FileMode.Create));
    
    AcroFields form = stamp.AcroFields;
    
    IDictionary<string, AcroFields.Item> fs = form.Fields;
    
    foreach (var f in fs)
    {
        form.SetField(f.Key, "some value");
    }
    
    stamp.Close();
    

    编辑:添加示例PDF文件

    我试着在这个PDF表单中填写两个字段(firstname和lastname)。

    这个 第一 文件是从base64字符串创建的窗体。

    d94b6076-983d-47db-b496-a0ba383deda4.pdf

    这个 第二 文件是填写两个字段后的输出。

    d94b6076-983d-47db-b496-a0ba383deda4_filled.pdf

    1 回复  |  直到 6 年前
        1
  •  1
  •   Community CDub    4 年前

    您的PDF包含一种特殊类型的数字签名,即使用权签名。用这样一个签名签名的PDF(使用Adobe为此任务生成的私钥)向Adobe Reader发出信号:在处理该PDF时,应激活某些额外的Adobe Reader功能。

    但是,如果签名无效,adobereader不仅不会激活那些额外的功能,甚至会取消激活其他一些对未签名文档有效的功能。

    你创造了你的 PdfStamper 这样地

    stamp = new PdfStamper(reader, new FileStream("path to filled PDF form file", FileMode.Create));
    

    该构造函数不初始化戳入 模式。因此,带戳记的PDF最终被写成一个新的PDF。这将使使用权限签名无效,并且Adobe Reader在再次打开PDF时会限制功能。

    顺便说一下,使用Adobe Reader打开PDF时,程序会告诉您:

    Adobe Reader pop-up

    如果你进去 但是,使用权限签名不会失效。可以使用不同的构造函数执行此操作:

    stamp = new PdfStamper(reader, new FileStream("path to filled PDF form file", FileMode.Create), '\0', true);
    

    true 激活附加模式。

    PdfReader reader = new PdfReader("path to PDF form file");
    reader.RemoveUsageRights();
    

    结果不再有使用权签名,尤其是没有失效的签名。因此,adobereader为这个文件提供了它的标准特性。

    不幸的是,保存XFA表单并不在其中,因此PDF可以编辑,但不能保存在Adobe Reader中。这可能不是你想要的。

    关于这些选项,请参见。 this old answer

    混合XFA/AcroForm定义

    该文件包含一个双表单定义,一个AcroForm表单定义是本机PDF表单类型,另一个XFA表单定义是仅将PDF用作传输容器的XML格式。

    XFA表单定义提供了更多功能,但只有Adobe软件才完全支持。对于混合表单,iText对将数据填充到两个表单定义中的支持有限。不过,这可能会失败,具体取决于XFA定义中使用的特性。

    在这种情况下,您可能需要删除XFA表单定义,而只使用acroformone。

    reader.Catalog.GetAsDict(PdfName.ACROFORM).Remove(PdfName.XFA);
    

    关于这种方法,请阅读 this answer 还有这个 iText article .