使用iText7提取PDF签名信息时遇无签名文档异常问题排查
解决iText7处理无签名PDF时SignatureUtil实例化异常的问题
我之前踩过一模一样的坑!这个异常的核心原因其实很简单:当PDF里没有任何数字签名时,SignatureUtil内部会尝试初始化一些需要写入权限的间接对象,但你当前只以只读模式打开了PdfDocument(仅传入PdfReader,没有关联PdfWriter),这就触发了「There is no associate PdfWriter for making indirects.」的错误。而有签名的PDF能正常运行,是因为此时SignatureUtil直接读取已存在的签名结构,不需要创建新对象,自然不会用到写入权限。
给你两个亲测有效的解决方案:
方案一:提前判断PDF是否有签名,按需实例化SignatureUtil
这种方式更高效,避免不必要的资源开销。我们可以先检查PDF是否存在签名域或文档级签名,再决定是否初始化SignatureUtil:
Using reader As New PdfReader(pdfPath), pdf As New PdfDocument(reader) Dim hasSignatures As Boolean = False ' 检查AcroForm中的签名域 Dim acroForm As PdfAcroForm = PdfAcroForm.GetAcroForm(pdf, False) If acroForm IsNot Nothing Then Dim signatureFields = acroForm.GetSignatureFields() hasSignatures = signatureFields.Count > 0 End If ' 额外检查文档级签名(比如DocMDP权限签名) Dim catalogDict = pdf.GetCatalog().GetPdfObject() If catalogDict.ContainsKey(PdfName.DocMDP) Then hasSignatures = True End If If hasSignatures Then ' 有签名时正常初始化并处理 Dim util As New SignatureUtil(pdf) Dim signatureNames = util.GetSignatureNames() ' 这里写你的签名信息获取逻辑 For Each name In signatureNames Dim sig = util.GetSignature(name) ' 提取签名者信息、时间戳等 Next Else ' 无签名时的处理逻辑 Console.WriteLine("当前PDF未包含任何数字签名") End If End Using
方案二:以读写模式打开PDF(适合必须初始化SignatureUtil的场景)
如果你的业务逻辑必须要实例化SignatureUtil,哪怕PDF没有签名,可以通过关联PdfWriter以读写模式打开文档。为了不修改原文件,我们可以用内存流来承接写入内容:
Using ms As New MemoryStream(), reader As New PdfReader(pdfPath), writer As New PdfWriter(ms), pdf As New PdfDocument(reader, writer) Try Dim util As New SignatureUtil(pdf) Dim signatureNames = util.GetSignatureNames() If signatureNames.Count = 0 Then Console.WriteLine("当前PDF未包含任何数字签名") Else ' 处理签名信息的逻辑 End If Catch ex As Exception ' 这里可以添加额外的异常捕获逻辑 Console.WriteLine($"处理出错:{ex.Message}") End Try End Using
个人更推荐方案一,因为它更轻量,不需要额外的写入操作,性能更好。
内容的提问来源于stack exchange,提问作者daustin
相关产品推荐
相关产品推荐

