You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:33:00