PDFBox 2.0.8签署PDF文档时出现无文件大小问题求助
解决PDF签名后生成文档无文件大小的问题
看起来你遇到的问题核心是签名流程不完整,没有把修改后的文档写入到输出流——你贴的代码只完成了密钥库的加载,后面最关键的签名创建、文档保存步骤都缺失了,这就导致内存里的PDF没有被持久化到磁盘,自然生成的文件是空的(无大小)。
我给你补全完整的签名流程,并指出几个必须注意的关键点:
可能的原因
- 没有执行文档保存操作:签名后的PDF只在内存中,必须调用
save或saveIncremental写入到文件/流 - 签名核心步骤缺失:没有创建签名对象、关联私钥和证书链
- 资源未正确关闭:输出流或
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"); } } }
关键注意事项
- 必须执行保存操作:
saveIncremental或save是把内存中的修改写入磁盘的核心步骤,你原来的代码完全没有这一步,这是文件为空的直接原因。 - 密钥库和凭证要正确:确保
CERT_FILE能被正确加载,ALIAS_PASS是密钥库和别名的正确密码(如果两者不同,需要分别传入)。 - 资源自动关闭:用try-with-resources语法自动关闭
FileOutputStream和PDDocument,避免资源泄漏导致写入不完整。 - 可见签名配置:如果需要在PDF上显示可见的签名框,还需要额外配置
VisibleSignature类,设置签名的位置、页面、外观等参数。
内容的提问来源于stack exchange,提问作者iperezmel78




