我需要使用iTextSharp编辑我的PDF文件。我有一个单选按钮和复选框,如下所述。
我想拥有以下内容:如果我在单选按钮上打了一个复选标记,则复选框必须显示为已选中。
在代码中,单选按钮具有值,但是当我第一次打开PDF文件时,不会选中该复选框。
当我再次在单选按钮上打勾时,它会变为可见。
这是我的代码;
PdfReader pdfReader = new PdfReader(pdfTemplate);
PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileStream(newFile, FileMode.OpenOrCreate));
AcroFields pdfFormFields = pdfStamper.AcroFields;
pdfFormFields.SetField("4a.0", "1"); // radio button
pdfFormFields.SetField("4a.1", "1"); // checkbox
pdfFormFields.SetField("4a.2", "2010"); // text box
答案 0 :(得分:6)
OP的代码中存在两个问题,导致独立于PDF的问题,以及导致PDF特定问题的PDF的特殊属性。
PdfStamper
OP提供的代码不会关闭PdfStamper
。这是必需的,但如果没有关闭压模,将不会写入重要信息:
...
pdfStamper.Close();
我认为,虽然OP确实关闭了压模但只是忘了将这一行复制到他的问题中,因为我在没有关闭压模的情况下观察到的错误是不同的。
FileMode
OP使用new FileStream(newFile, FileMode.OpenOrCreate)
来创建文件输出流。文件模式OpenOrCreate
记录为:
// Summary:
// Specifies that the operating system should open a file if it exists; otherwise,
// a new file should be created. If the file is opened with FileAccess.Read,
// System.Security.Permissions.FileIOPermissionAccess.Read permission is required.
// If the file access is FileAccess.Write, System.Security.Permissions.FileIOPermissionAccess.Write
// permission is required. If the file is opened with FileAccess.ReadWrite,
// both System.Security.Permissions.FileIOPermissionAccess.Read and System.Security.Permissions.FileIOPermissionAccess.Write
// permissions are required.
OpenOrCreate = 4,
因此,如果newFile
已经存在,则压模会写入此文件,如果压模创建的文件比以前存在的文件短,则前一个内容的结尾部分仍然存在并有效地使PDF无效
所以请使用FileMode.Create
而不是记录为:
// Summary:
// Specifies that the operating system should create a new file. If the file
// already exists, it will be overwritten. This requires System.Security.Permissions.FileIOPermissionAccess.Write
// permission. FileMode.Create is equivalent to requesting that if the file
// does not exist, use System.IO.FileMode.CreateNew; otherwise, use System.IO.FileMode.Truncate.
// If the file already exists but is a hidden file, an System.UnauthorizedAccessException
// exception is thrown.
Create = 2,
OP的代码在追加模式下不使用压模。对于以前签名的文档,这会导致签名中断。在文件的情况下,OP共享那里确实存在签名,即所谓的使用权签名。因此,再次打开PDF时,Adobe Reader会显示:
所以请使用追加模式(或完全丢弃使用权签名):
PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileStream(newFile, FileMode.Create), '\0', true);
正如在对该问题的评论中已经提到的那样:
表单有点滥用PDF。
4a.0
和4a.1
都是没有 Ff (字段标志)条目的按钮字段,即对于这两个字段,flags值是默认值0,这意味着两个按钮字段是复选框字段,因为既没有设置按钮也没有设置Radio标志。但两者都表现得像单选按钮一样,除了关闭之外,还有多个孩子不知道常见的外观状态。 PDF功能的这种使用是互操作性的障碍。
但iText对此没有任何问题。不过,PDF应该是固定的。
这是有问题的PDF部分:
执行OP的代码时,会发现4a.0
的顶部元素已被标记,但在子字段4a.1
或4a.2
中看不到差异。
原因是虽然顶级元素(4a.0
中的单选按钮)始终可见,但依赖元素4a.1
,4a.2
和4a.3
(并且类似地,OP文件中依赖于其他顶级单选按钮选项的元素也被标记为隐藏,因此它们的值不会显示。
在PDF查看器中,依赖字段的隐藏标志会在选中时通过关联的顶级单选按钮的JavaScript操作重置。因此,从属字段值变得可见。
另一方面,iTextSharp不包含执行此类操作的JavaScript引擎。因此,这些领域仍然是隐藏的。因此,请不要只设置字段值,还要重置相关的隐藏标志:
pdfFormFields.SetField("4a.1", "1"); // checkbox
pdfFormFields.SetFieldProperty("4a.1", "clrflags", 2, null);
pdfFormFields.SetField("4a.2", "2010"); // text box
pdfFormFields.SetFieldProperty("4a.2", "clrflags", 2, null);
包含所有更改的来源是:
PdfReader pdfReader = new PdfReader(pdfTemplate);
PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileStream(newFile, FileMode.Create), '\0', true);
AcroFields pdfFormFields = pdfStamper.AcroFields;
pdfFormFields.SetField("4a.0", "1"); // radio button
pdfFormFields.SetField("4a.1", "1"); // checkbox
pdfFormFields.SetFieldProperty("4a.1", "clrflags", 2, null);
pdfFormFields.SetField("4a.2", "2010"); // text box
pdfFormFields.SetFieldProperty("4a.2", "clrflags", 2, null);
pdfStamper.Close();
,结果如下: