im trying to create a PDF/A-3 with itextpdf-5.4.5 and itext-pdfa-5.4.5. When i set the PdfFileSpecification, i get the following Exception:
com.itextpdf.text.pdf.PdfAConformanceException: Embedded file shall contain valid Params key.
This is the part where i create the PdfDictionary:
PdfDictionary params = new PdfDictionary();
params.put(PdfName.MODDATE, new PdfDate());
PdfFileSpecification fileSpec = PdfFileSpecification.fileEmbedded(
writer, "./src/main/resources/com/itextpdf/invoice.xml", "invoice.xml", null, false, "text/xml", params);
I found the method where the check happens, but i dont find any solution:
com.itextpdf.text.pdf.internal.PdfA3Checker.checkEmbeddedFile
protected void checkEmbeddedFile(PdfDictionary embeddedFile) {
PdfDictionary params = getDirectDictionary(embeddedFile.get(PdfName.PARAMS));
if (params == null) {
throw new PdfAConformanceException(embeddedFile, MessageLocalization.getComposedMessage("embedded.file.shall.contain.valid.params.key"));
}
Any idea? Thank you in advance!
PDF/A-3 has some special requirements concerning embedded files, among them
An embedded file's stream dictionary should contain a Params key whose value shall be a dictionary containing at least a ModDate key whose value shall be the latest modification date of the source file.
(Annex E.1 of ISO 19000-3)
iText support explains on PDF/A-3 with iText how to create PDF/A-3 compliant PDFs from scratch, and they also demonstrate there how to embed files in a PDF/A-3 compliant manner, their sample code:
PdfDictionary parameters = new PdfDictionary();
parameters.put(PdfName.MODDATE, new PdfDate());
PdfFileSpecification fileSpec = PdfFileSpecification.fileEmbedded(
writer, "./src/main/resources/com/itextpdf/invoice.xml",
"invoice.xml", null, "application/xml", parameters, 0);
fileSpec.put(new PdfName("AFRelationship"), new PdfName("Data"));
writer.addFileAttachment("invoice.xml", fileSpec);
PdfArray array = new PdfArray();
array.add(fileSpec.getReference());
writer.getExtraCatalog().put(new PdfName("AF"), array);
This example also adds the associated file entry (AF) to the Catalog which is another requirement.
BTW, strictly speaking the Params dictionary is only required on a should base, not shall. Thus, this is actually a recommendation and there can be valid PDF/A-3 documents with attachments in the wild which do not have this entry.
As there is no apparent reason why iText would be better off not following this recommendation when creating PDF/A-3 files, though, the strict interpretation by its checks is ok.
The check the OP found has been introduced recently. This check already is triggered while storing the file in the PDF file. Unfortunately at this time the params dictionary has not yet been assigned, only a reference has been reserved. Thus, the check fails, even though shortly after the dictionary would have been written.
From PdfFileSpecification.java:
stream.put(PdfName.TYPE, PdfName.EMBEDDEDFILE);
stream.flateCompress(compressionLevel);
PdfDictionary param = new PdfDictionary();
if (fileParameter != null) {
param.merge(fileParameter);
}
if (!param.contains(PdfName.MODDATE)) {
param.put(PdfName.MODDATE, new PdfDate());
}
if (fileStore != null) {
param.put(PdfName.SIZE, new PdfNumber(stream.getRawLength()));
stream.put(PdfName.PARAMS, param);
}
else
stream.put(PdfName.PARAMS, refFileLength);
if (mimeType != null)
stream.put(PdfName.SUBTYPE, new PdfName(mimeType));
ref = writer.addToBody(stream).getIndirectReference();
During this operation the check happens (and fails).
if (fileStore == null) {
stream.writeLength();
param.put(PdfName.SIZE, new PdfNumber(stream.getRawLength()));
writer.addToBody(param, refFileLength);
}
And here, directly thereafter, the params would have been written.
PdfFileSpecification.fileEmbedded allows you to present the data as a byte[] instead of as a file in the file system. As you can see in the source above the processing differs in that case: fileStore contains that byte[] argument. If you follow up on the fileStore use in there, you'll see that for a non-null value of it the params dictionary is written as a direct object and, therefore, present in the test.
Thus, you can use iText 5.4.5 for PDF/A-3 file attachments if you supply the files as byte[] instances instead.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With