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

使用PDFBox转换含电子签名PDF为图片时缺失内容求助

PDFBox渲染带签名PDF丢失内容问题分析与解决方案

问题现象

使用PDFBox 3.0.2(及旧版本)渲染含电子签名的PDF时,签名区域的William文本无法被渲染,其余内容正常显示。

原因分析

电子签名的显示内容(如William)属于PDF的AcroForm签名域外观,默认情况下:

  • PDFRenderer在RenderDestination.PRINT模式下可能会过滤部分屏幕优先的元素;
  • PDFBox加载文档时,若未正确保留AcroForm相关数据,会导致签名外观无法被加载渲染;
  • 签名域的外观可能被标记为仅在特定场景显示,PRINT模式下被隐藏。

解决方案

1. 调整渲染目标参数

将RenderDestination.PRINT替换为RenderDestination.SCREEN,该模式会优先保留屏幕显示的所有元素,包括签名外观:

try (PDDocument document = Loader.loadPDF(new File("test-signed.pdf"))) {
    PDFRenderer pdfRenderer = new PDFRenderer(document);
            
    // 替换RenderDestination为SCREEN
    BufferedImage bufferedImage = pdfRenderer.renderImage(0, 300 / 72f, ImageType.RGB, RenderDestination.SCREEN);

    File file = new File("output.png");
    ImageIO.write(bufferedImage, "png", file);
}

2. 确保AcroForm被正确加载

如果上述方法无效,可显式设置加载参数保留AcroForm,并强制渲染所有注释:

// 设置加载参数,保留AcroForm
LoadOptions options = new LoadOptions();
options.setPreserveAcroForm(true);

try (PDDocument document = Loader.loadPDF(new File("test-signed.pdf"), options)) {
    PDFRenderer pdfRenderer = new PDFRenderer(document);
    // 启用注释渲染
    pdfRenderer.setRenderAnnotations(true);
            
    BufferedImage bufferedImage = pdfRenderer.renderImage(0, 300 / 72f, ImageType.RGB, RenderDestination.SCREEN);

    File file = new File("output.png");
    ImageIO.write(bufferedImage, "png", file);
}

3. 手动绘制签名域外观

若前两种方法仍失效,可手动遍历签名域,提取其外观并绘制到渲染后的图片上:

try (PDDocument document = Loader.loadPDF(new File("test-signed.pdf"))) {
    PDFRenderer pdfRenderer = new PDFRenderer(document);
    BufferedImage bufferedImage = pdfRenderer.renderImage(0, 300 / 72f, ImageType.RGB, RenderDestination.SCREEN);
    Graphics2D g2d = bufferedImage.createGraphics();

    // 获取AcroForm及签名域
    PDAcroForm acroForm = document.getDocumentCatalog().getAcroForm();
    if (acroForm != null) {
        for (PDField field : acroForm.getFields()) {
            if (field instanceof PDSignatureField) {
                PDSignatureField signatureField = (PDSignatureField) field;
                PDAppearanceDictionary appearance = signatureField.getAppearance();
                if (appearance != null) {
                    PDAppearanceStream appearanceStream = appearance.getNormalAppearance();
                    if (appearanceStream != null) {
                        // 转换外观流为BufferedImage并绘制
                        float scale = 300 / 72f;
                        Rectangle2D rect = signatureField.getWidgets().get(0).getRectangle().getRectangle2D();
                        BufferedImage sigImage = appearanceStream.getImage(document);
                        g2d.drawImage(sigImage, 
                            (int)(rect.getX() * scale), 
                            (int)((document.getPage(0).getMediaBox().getHeight() - rect.getY() - rect.getHeight()) * scale), 
                            (int)(rect.getWidth() * scale), 
                            (int)(rect.getHeight() * scale), 
                            null);
                    }
                }
            }
        }
    }

    g2d.dispose();
    File file = new File("output.png");
    ImageIO.write(bufferedImage, "png", file);
}

内容的提问来源于stack exchange,提问作者dat pham cao hoang

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 20:33:21