You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

PDFBox 2.0.8签署PDF文档时出现无文件大小问题求助

解决PDF签名后生成文档无文件大小的问题

看起来你遇到的问题核心是签名流程不完整,没有把修改后的文档写入到输出流——你贴的代码只完成了密钥库的加载,后面最关键的签名创建、文档保存步骤都缺失了,这就导致内存里的PDF没有被持久化到磁盘,自然生成的文件是空的(无大小)。

我给你补全完整的签名流程,并指出几个必须注意的关键点:

可能的原因

  • 没有执行文档保存操作:签名后的PDF只在内存中,必须调用savesaveIncremental写入到文件/流
  • 签名核心步骤缺失:没有创建签名对象、关联私钥和证书链
  • 资源未正确关闭:输出流或PDDocument未关闭,导致写入不完整

完整的签名示例代码

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature;

import java.io.File;
import java.io.FileOutputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.util.Calendar;

public class PdfSigner {
    private static final String CERT_FILE = "/your-keystore-path.jks"; // 替换成你的密钥库路径
    private static final String ALIAS_PASS = "your-keystore-password"; // 替换成你的密码

    public static void sign(PDDocument doc, String outputFilePath) throws Exception {
        System.out.println("Document pages ? " + doc.getNumberOfPages());

        // 1. 加载密钥库
        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
        char[] password = ALIAS_PASS.toCharArray();
        ks.load(PdfSigner.class.getResourceAsStream(CERT_FILE), password);

        // 2. 获取签名所需的私钥和证书链
        String alias = ks.aliases().nextElement(); // 如果有多个别名,需要指定目标别名
        PrivateKey privateKey = (PrivateKey) ks.getKey(alias, password);
        Certificate[] certChain = ks.getCertificateChain(alias);

        // 3. 创建并配置签名对象
        PDSignature signature = new PDSignature();
        signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE); // 标准签名过滤器
        signature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED); // 分离式签名(推荐)
        signature.setName("你的签名名称");
        signature.setLocation("签名地点");
        signature.setReason("签名原因");
        signature.setSignDate(Calendar.getInstance()); // 签名时间

        // 4. 将签名添加到文档
        doc.addSignature(signature);

        // 5. 保存并完成签名(关键步骤!)
        try (FileOutputStream fos = new FileOutputStream(outputFilePath)) {
            // 增量保存适合已存在的PDF,减少文件大小;新文档也可以用doc.save(fos)
            doc.saveIncremental(fos);
        } finally {
            // 必须关闭文档释放资源
            doc.close();
        }

        System.out.println("签名完成,文件已保存至: " + outputFilePath);
    }

    // 测试调用示例
    public static void main(String[] args) throws Exception {
        try (PDDocument doc = PDDocument.load(new File("input.pdf"))) {
            sign(doc, "signed_output.pdf");
        }
    }
}

关键注意事项

  1. 必须执行保存操作saveIncrementalsave是把内存中的修改写入磁盘的核心步骤,你原来的代码完全没有这一步,这是文件为空的直接原因。
  2. 密钥库和凭证要正确:确保CERT_FILE能被正确加载,ALIAS_PASS是密钥库和别名的正确密码(如果两者不同,需要分别传入)。
  3. 资源自动关闭:用try-with-resources语法自动关闭FileOutputStreamPDDocument,避免资源泄漏导致写入不完整。
  4. 可见签名配置:如果需要在PDF上显示可见的签名框,还需要额外配置VisibleSignature类,设置签名的位置、页面、外观等参数。

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

火山引擎 最新活动