如何在单页PDF中添加多个电子签名?(iText7 .NET报错解决)
问题原因
调用SignDetached完成签名后,PdfSigner会自动关闭文档相关的流对象,同一个PdfSigner实例仅能完成一次签名操作。你的代码尝试复用同一个PdfSigner执行多次签名,第二次调用时文档已被关闭,因此抛出Document was closed异常。
解决方案
每次签名都需要基于上一次签名后的PDF文件,重新创建PdfReader和PdfSigner实例,并启用追加模式。具体修改如下:
修改后的完整代码
public void sign() { string KEYSTORE = @"D:\resources\cert.pfx"; char[] PASSWORD = "password".ToCharArray(); Pkcs12Store pk12 = new Pkcs12Store(new FileStream(KEYSTORE, FileMode.Open, FileAccess.Read), PASSWORD); string alias = null; foreach (object a in pk12.Aliases) { alias = ((string)a); if (pk12.IsKeyEntry(alias)) { break; } } ICipherParameters pk = pk12.GetKey(alias).Key; X509CertificateEntry[] ce = pk12.GetCertificateChain(alias); IX509Certificate[] chain = new IX509Certificate[ce.Length]; for (int k = 0; k < ce.Length; ++k) { chain[k] = new X509CertificateBC(ce[k].Certificate); } string SRC = "D:\\resources\\PR.pdf"; // 临时文件存储中间签名结果 string temp1 = "D:\\resources\\PR_signed_temp1.pdf"; string DEST = "D:\\resources\\PR_signed.pdf"; Rectangle requesterPosition = new Rectangle(10, 140, 130, 180); Rectangle headOfPosition = new Rectangle(160, 140, 300, 180); Rectangle thirdSignPosition = new Rectangle(480, 140, 130, 180); // 第三个签名位置 // 第一次签名:原文件→临时文件 SignSingleDocument(SRC, temp1, chain, pk, requesterPosition); // 第二次签名:临时文件→最终文件 SignSingleDocument(temp1, DEST, chain, pk, headOfPosition); // 第三次签名:基于最终文件继续追加(如果需要) // SignSingleDocument(DEST, DEST, chain, pk, thirdSignPosition); // 清理临时文件(可选) File.Delete(temp1); } public void SignSingleDocument(string srcPath, string destPath, IX509Certificate[] chain, ICipherParameters pk, Rectangle rect) { using (PdfReader reader = new PdfReader(srcPath)) { using (FileStream fs = new FileStream(destPath, FileMode.Create)) { PdfSigner signer = new PdfSigner(reader, fs, new StampingProperties().PreserveEncryption().UseAppendMode()); signer.SetFieldName(signer.GetNewSigFieldName()); // 仅第一次签名需要设置认证级别,后续签名无需重复设置(设置也不会改变原有级别) signer.SetCertificationLevel(PdfSigner.CERTIFIED_FORM_FILLING_AND_ANNOTATIONS); PdfSignatureAppearance appearance = signer.GetSignatureAppearance(); appearance.SetReason("test signature") .SetLocation("VN") .SetPageRect(rect) .SetPageNumber(1); IExternalSignature pks = new PrivateKeySignature(new PrivateKeyBC(pk), DigestAlgorithms.SHA256); signer.SignDetached(pks, chain, null, null, null, 0, PdfSigner.CryptoStandard.CMS); } } }
关键说明
- 每次签名创建独立的
PdfReader和PdfSigner实例,确保文档流未被关闭,可正常执行签名操作。 - 使用临时文件存储中间结果,避免签名失败导致最终文件损坏,完成所有签名后可删除临时文件。
- 认证级别
CERTIFIED_FORM_FILLING_AND_ANNOTATIONS允许后续添加签名,符合多签名场景需求;若设置为CERTIFIED_NO_CHANGES_ALLOWED,后续将无法添加任何签名,需注意区分。
内容的提问来源于stack exchange,提问作者Giang
相关产品推荐
相关产品推荐

