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

如何使用PDFBox在单次签名会话中添加多可视化签名并完成外部签名?

解决PDFBox单次签名会话添加多可见签名的问题

问题根源

  1. 空间不足异常:未设置PreferredSignatureSize时,PDFBox默认预留的签名空间不足以容纳多个签名的完整数据,直接触发IOException。
  2. 仅最后一个签名可见:复用同一SignatureOptions实例或未为每个签名分配独立的外观图层/位置,后续签名的外观会覆盖之前的签名内容。

修复方案

1. 为每个签名创建独立的签名配置

禁止复用SignatureOptions,每个签名都生成新实例,并根据签名数量设置足够大的PreferredSignatureSize(建议单签名预留40000字节以上,多签名按数量累加):

for (SignatureDefinition def : signatureDefinitions) {
    // 每个签名都新建SignatureOptions
    SignatureOptions signatureOptions = new SignatureOptions();
    // 按签名数量预留足够空间,示例为3个签名预留120000字节
    signatureOptions.setPreferredSignatureSize(40000 * signatureDefinitions.size());
    
    // 配置当前签名的页面与位置
    signatureOptions.setPage(def.getPageIndex());
    PDRectangle signRect = new PDRectangle(def.getLeft(), def.getBottom(), def.getWidth(), def.getHeight());
    signatureOptions.setVisualSignature(buildUniqueVisualSignature(document, signRect, def.getSignerName()));
    
    // 执行签名
    signer.sign(signatureOptions);
    // 及时关闭当前配置,释放资源
    signatureOptions.close();
}

2. 生成独立的签名外观

每个签名的可视化外观必须创建独立的PDFormXObject,避免复用导致的覆盖:

private PDFormXObject buildUniqueVisualSignature(PDDocument doc, PDRectangle rect, String signerName) throws IOException {
    PDFormXObject visualForm = new PDFormXObject(doc);
    visualForm.setBBox(rect);
    visualForm.setResources(new PDResources());
    
    try (PDPageContentStream contentStream = new PDPageContentStream(doc, visualForm)) {
        // 绘制签名边框
        contentStream.addRect(rect.getLowerLeftX(), rect.getLowerLeftY(), rect.getWidth(), rect.getHeight());
        contentStream.setStrokingColor(Color.LIGHT_GRAY);
        contentStream.stroke();
        
        // 添加签名人信息文本
        contentStream.beginText();
        contentStream.setFont(PDType1Font.HELVETICA_BOLD, 12);
        contentStream.setNonStrokingColor(Color.BLACK);
        contentStream.newLineAtOffset(rect.getLowerLeftX() + 10, rect.getLowerLeftY() + 15);
        contentStream.showText("签署人:" + signerName);
        contentStream.endText();
    }
    return visualForm;
}

3. 确保签名位置不重叠

遍历signatureDefinitions时,需保证每个签名的页面坐标不重叠,可通过配置文件或业务逻辑为每个签名分配唯一的页面区域(如不同页面、同一页面的不同象限)。

4. 维持单次会话的增量签名流程

全程保持PDDocument处于打开状态,所有签名完成后再统一关闭文档,确保PDFBox以增量更新模式追加每个签名,而非覆盖原有内容。

内容的提问来源于stack exchange,提问作者H20

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 23:43:17