[
https://issues.apache.org/jira/browse/PDFBOX-3743?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15955249#comment-15955249
]
Tilman Hausherr commented on PDFBOX-3743:
-----------------------------------------
Here's your code modified so that it runs:
{code}
public class PDFBox3743SigProblem
{
static String dir = "XXXXXXXXXXXXXXXXXXX";
public static void main(String[] args) throws IOException,
URISyntaxException
{
try (PDDocument doc = PDDocument.load(new File(dir, "xxx.pdf")))
{
if (false)
{
doc.addSignature(
new PDSignature(),
is -> new byte[0],
getSignatureOptions(doc, new File(dir, "sig.jpg"))
);
// IOException when gc(): COSStream has been closed and cannot
be read. Perhaps its enclosing PDDocument has been closed?
}
else
{
SignatureOptions signatureOptions = getSignatureOptions(doc,
new File(dir, "sig.jpg"));
doc.addSignature(
new PDSignature(),
is -> new byte[0],
signatureOptions
);
// works
}
System.gc();
try (FileOutputStream out = new FileOutputStream(new File(dir,
"xxx-signed.pdf")))
{
doc.saveIncremental(out);
}
}
}
private static SignatureOptions getSignatureOptions(PDDocument doc, File
signatureImage) throws IOException
{
SignatureOptions signatureOptions = new SignatureOptions();
PDVisibleSignDesigner visibleSignature;
try (InputStream input = new FileInputStream(signatureImage))
{
visibleSignature = new PDVisibleSignDesigner(doc, input, 1);
}
PDVisibleSigProperties visibleSignatureProperties = new
PDVisibleSigProperties();
visibleSignatureProperties.setPdVisibleSignature(visibleSignature).buildSignature();
signatureOptions.setVisualSignature(visibleSignatureProperties);
return signatureOptions;
}
}
{code}
Look at the first "if" statement. When the condition is "true", the code fails.
When it is false, the code succeeds. It is related to signatureOptions falling
out of scope. You might also have seen this log output:
{quote}
WARN \[Finalizer] org.apache.pdfbox.cos.COSDocument:478 - Warning: You did not
close a PDF Document
{quote}
That one means that PDFBox closes a COSDocument object (that is in the
signatureOptions) for you. I made a modification to SignatureOptions to see if
finalize is called before things go bad, and yes it is :-(
Your problem reminds me of this
https://stackoverflow.com/questions/42208399/pdfbox-how-to-clone-a-page
see the comment by mkl.
So signatureOptions goes out of scope, and thus COSDocument is also not needed
anymore either... but the signed PDF keeps references of some of the streams in
the COSDocument. Because the COSDocument is no longer referenced, it gets
closed at the gc() moment, which also closes streams that are still needed. So
the solution in the CreateVisibleSignature example is the correct one: keep
signatureOptions until done, and close it yourself (i.e. even the "false"
branch here is not really correct!!!). I will add a comment into the
CreateVisibleSignature example and improve the javadoc of
SignatureOptions.close().
Thus, TODO for you: add {{signatureOptions.close();}} as last statement.
Btw your code is incorrect, it doesn't sign anything. Unlike the
CreateVisibleSignature example, which can sign.
> Running GC between signing and saving document closes stream
> ------------------------------------------------------------
>
> Key: PDFBOX-3743
> URL: https://issues.apache.org/jira/browse/PDFBOX-3743
> Project: PDFBox
> Issue Type: Bug
> Affects Versions: 2.0.5
> Environment: Ubuntu 16.04 64-bit, play framework 1.5
> Reporter: Dmitri Ess
>
> Running GC between signing and saving document closes stream and signing
> process fails. It happens only if signature image is added via
> PDVisibleSignDesigner e.g.
> import org.apache.commons.io.IOUtils;
> import org.apache.pdfbox.pdmodel.PDDocument;
> import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature;
> import
> org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureOptions;
> import
> org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDVisibleSigProperties;
> import
> org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDVisibleSignDesigner;
> import java.io.*;
> import java.net.URISyntaxException;
> import static java.lang.Thread.currentThread;
> public class Foo {
> public static void main(String[] args) throws IOException,
> URISyntaxException {
> byte[] unsignedPdf = getResourceAsBytes("pdf-sample.pdf");
> try (PDDocument doc = PDDocument.load(unsignedPdf)) {
> doc.addSignature(
> new PDSignature(),
> is -> new byte[0],
> getSignatureOptions(doc, getFile("util/test-pdf-signature.jpg"))
> );
> System.gc();
> try (FileOutputStream out = new
> FileOutputStream(File.createTempFile("signed", ".pdf"))) {
> doc.saveIncremental(out);
> }
> }
> }
> private static SignatureOptions getSignatureOptions(PDDocument doc, File
> signatureImage) throws IOException {
> SignatureOptions result = new SignatureOptions();
> PDVisibleSignDesigner visibleSignature;
> try (InputStream input = new FileInputStream(signatureImage)) {
> visibleSignature = new PDVisibleSignDesigner(doc, input, 1);
> }
> PDVisibleSigProperties visibleSignatureProperties = new
> PDVisibleSigProperties();
>
> visibleSignatureProperties.setPdVisibleSignature(visibleSignature).buildSignature();
> result.setVisualSignature(visibleSignatureProperties);
> return result;
> }
> public static byte[] getResourceAsBytes(String filePath) throws
> IOException, URISyntaxException {
> return IOUtils.toByteArray(getFile(filePath).toURI());
> }
> public static File getFile(String filePath) throws URISyntaxException {
> return new
> File(currentThread().getContextClassLoader().getResource(filePath).toURI());
> }
> }
> constantly fails with:
> Exception in thread "main" java.io.IOException: COSStream has been closed and
> cannot be read. Perhaps its enclosing PDDocument has been closed?
> at org.apache.pdfbox.cos.COSStream.checkClosed(COSStream.java:77)
> at
> org.apache.pdfbox.cos.COSStream.createRawInputStream(COSStream.java:125)
> at
> org.apache.pdfbox.pdfwriter.COSWriter.visitFromStream(COSWriter.java:1203)
> at org.apache.pdfbox.cos.COSStream.accept(COSStream.java:383)
> at org.apache.pdfbox.cos.COSObject.accept(COSObject.java:158)
> at
> org.apache.pdfbox.pdfwriter.COSWriter.doWriteObject(COSWriter.java:522)
> at
> org.apache.pdfbox.pdfwriter.COSWriter.doWriteObjects(COSWriter.java:460)
> at org.apache.pdfbox.pdfwriter.COSWriter.doWriteBody(COSWriter.java:444)
> at
> org.apache.pdfbox.pdfwriter.COSWriter.visitFromDocument(COSWriter.java:1099)
> at org.apache.pdfbox.cos.COSDocument.accept(COSDocument.java:419)
> at org.apache.pdfbox.pdfwriter.COSWriter.write(COSWriter.java:1370)
> at
> org.apache.pdfbox.pdmodel.PDDocument.saveIncremental(PDDocument.java:1276)
> at Foo.main(Foo.java:27)
--
This message was sent by Atlassian JIRA
(v6.3.15#6346)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]