当前位置: 首页 > 知识库问答 >
问题:

登录Apache PDFBox 2.0时“您没有关闭PDF文档”

严易安
2023-03-14

在对PDF文档进行数字签名后,我在Apache PDFBox中关闭了PDF文档。我收到警告:当我关闭实例时,你没有关闭PDF文档。只有一个地方可以创建PDDocument,并正确关闭它。

代码:

private byte[] buildDocument(File pdfToSign, PDVisibleSigProperties visibleSigProperties) throws Exception
{
    FileOutputStream fos = null;
    PDDocument doc = null;
    try
    {
        String signedPdfName = pdfToSign.getName().substring(0, pdfToSign.getName().indexOf("."));
        File signedFile = File.createTempFile(signedPdfName + "_signed", null);
        signedFile.deleteOnExit();

        fos = new FileOutputStream(signedFile);
        doc = PDDocument.load(pdfToSign);

        // create signature dictionary
        PDSignature signature = new PDSignature();
        signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);

        // subfilter for basic and PAdES Part 2 signatures
        signature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);
        signature.setName(visibleSigProperties.getSignerName());
        signature.setLocation(visibleSigProperties.getSignerLocation());
        signature.setReason(visibleSigProperties.getSignatureReason());

        // the signing date, needed for valid signature
        signature.setSignDate(Calendar.getInstance());

        // register signature dictionary and sign interface
        SignatureOptions options = new SignatureOptions();
        options.setVisualSignature(visibleSigProperties);
        options.setPage(visibleSigProperties.getPage() - 1);
        doc.addSignature(signature, this, options);
        byte[] pdfInBytes = IOUtils.toByteArray(new FileInputStream(signedFile));
        return pdfInBytes;
    }
    finally
    {
        if(doc != null)
        {
            // write incremental (only for signing purpose)
            doc.saveIncremental(fos);
            doc.close();
        }
        if(fos != null)
        {
            fos.flush();
            fos.close();
        }
    }

}

签名接口实现

/**
 * Signature Interface implementation
 * This is called by pdf Box 
 */
public byte[] sign(InputStream content) throws IOException
{
    try
    {
        List<Certificate> certList = new ArrayList<Certificate>();
        certList.add(getCertificate());
        Store certs = new JcaCertStore(certList);
        CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
        org.bouncycastle.asn1.x509.Certificate cert = org.bouncycastle.asn1.x509.Certificate.getInstance(ASN1Primitive.fromByteArray(getCertificate().getEncoded()));
        ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA256WithRSA").build(getPrivateKey());
        gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().build()).build(sha1Signer, new X509CertificateHolder(cert)));
        gen.addCertificates(certs);
        CMSProcessableInputStream msg = new CMSProcessableInputStream(content);
        CMSSignedData signedData = gen.generate(msg, false);
        return signedData.getEncoded();
    }
    catch (GeneralSecurityException e)
    {
        throw new IOException(e);
    }
    catch (CMSException e)
    {
        throw new IOException(e);
    }
    catch (OperatorCreationException e)
    {
        throw new IOException(e);
    }
}

共有1个答案

邵俊才
2023-03-14

请在关闭文档后关闭选项

    if(doc != null)
    {
        // write incremental (only for signing purpose)
        doc.saveIncremental(fos);
        doc.close();
        IOUtils.closeQuietly(options);
    }

原因是options包含一个可视签名模板。

 类似资料:
  • 我正在尝试加载PDF文档并打印它。整个过程都正常,但我收到了以下警告“警告:您没有关闭PDF文档”,我不明白为什么在我关闭文档后会出现这种情况。它出现在第11行(job.print();)。因为它是在打印时发生的,所以我无法调试它。

  • 我想按页分割pdf到图像文件,但我得到了警告:你没有关闭PDF文档循环时renderImageBackDPI仍然有警告更新代码: 错误循环 总警告与页数相同。。。我已经尝试关闭但无法工作,这个过程使我的服务器成为java。lang.OutOfMemoryError:Java堆空间 更新: 这是调用拆分方法的代码......

  • 问题内容: 我一直在对我们的一个宠物项目进行代码审查(通常使用诸如FindBugs之类的工具),并且FindBugs将以下代码标记为错误的(伪代码): 错误是此代码可能不会释放资源。我发现ResultSet和Statement没有关闭,所以我最终将它们关闭: 但是我在许多项目(来自许多公司)中遇到了上述模式,没有人关闭ResultSets或Statements。 关闭连接时,是否关闭了Result

  • 我有一个网站,作为一个远程Git回购从BitBucket.com拉使用一个SSH别名。我可以在服务器上手动启动ssh-agent,但每次通过ssh登录时都必须这样做。 我手动启动ssh-agent: 然后我添加代理: 当我这么做的时候,它就会出现:

  • 为了进一步清晰,我添加了代码段。我正在使用Java Selenium-testng并尝试用3个帐户登录到一个网站zoho.com并验证是否成功。我已经看过一些类似的问题,但还没有找到一个解决方案,适用于我的情况。 我在@BeforeMethod中实例化了ChromeDriver。然后用first帐号登录网站,用@aftermethod关闭浏览器。我必须用Driver=new ChromeDrive

  • 我的控制台被来自ChromeDriver和IEDriver的不想要的日志消息填满了。 我尝试过:但是不起作用。我尝试了的各种实现,但都不起作用。