I'm trying to create a PDF/A-3A file with an attached plaint text file using the example CreatePDFA but the validation of the resulting file fails using VeraPDF validator. I'm using PDFBox v.3.0.0 RC1.
Error: The value of the Length key specified in the stream dictionary shall match the number of bytes in the file following the LINE FEED (0Ah) character after the stream keyword and preceding the EOL marker before the endstream keyword.
Error location is: root/indirectObjects[0](22 0)/directObject[0]
How can I add the correct length to the PDF file? The attachment code is as follows:
private void attachFile(PDDocument doc, File file, String mediaType, String description) throws IOException {
long fileSize = file.length();
BasicFileAttributes fileAttr = Files.readAttributes(file.toPath(), BasicFileAttributes.class);
GregorianCalendar creationTimeCal = new GregorianCalendar();
creationTimeCal.setTimeInMillis(fileAttr.creationTime().toMillis());
GregorianCalendar modifiedTimeCal = new GregorianCalendar();
modifiedTimeCal.setTimeInMillis(fileAttr.lastModifiedTime().toMillis());
// embedded files are stored in a named tree
PDEmbeddedFilesNameTreeNode efTree = new PDEmbeddedFilesNameTreeNode();
// first create the file specification, which holds the embedded file
PDComplexFileSpecification fs = new PDComplexFileSpecification();
// use both methods for backwards, cross-platform and cross-language compatibility.
fs.setFile(file.getName());
fs.setFileUnicode(file.getName());
COSDictionary dict = fs.getCOSObject();
dict.setName("AFRelationship", "Alternative");
try (InputStream is = Files.newInputStream(file.toPath(), StandardOpenOption.READ)) {
PDEmbeddedFile ef = new PDEmbeddedFile(doc, is);
// now lets some of the optional parameters
ef.setSubtype(mediaType);
ef.setSize((int) fileSize);
ef.setCreationDate(creationTimeCal);
ef.setModDate(modifiedTimeCal);
ef.setDecodedStreamLength((int) fileSize);
// use both methods for backwards, cross-platform and cross-language compatibility.
fs.setEmbeddedFile(ef);
fs.setEmbeddedFileUnicode(ef);
fs.setFileDescription(StringUtils.defaultString(description, file.getName()));
// create a new tree node and add the embedded file
String attachmentName = StringUtils.defaultString(file.getName(),description);
PDEmbeddedFilesNameTreeNode treeNode = new PDEmbeddedFilesNameTreeNode();
treeNode.setNames(Collections.singletonMap(attachmentName, fs));
// add the new node as kid to the root node
List<PDEmbeddedFilesNameTreeNode> kids = new ArrayList<>();
kids.add(treeNode);
efTree.setKids(kids);
// add the tree to the document catalog
PDDocumentNameDictionary names = new PDDocumentNameDictionary(doc.getDocumentCatalog());
names.setEmbeddedFiles(efTree);
doc.getDocumentCatalog().setNames(names);
// AF entry (Array) in catalog with the FileSpec
COSArray cosArray = new COSArray();
cosArray.add(fs);
doc.getDocumentCatalog().getCOSObject().setItem("AF", cosArray);
// show attachments panel in some viewers
doc.getDocumentCatalog().setPageMode(PageMode.USE_ATTACHMENTS);
}
}
The PDF file can be found here: https://gofile.io/d/FuWIdV
The latest version 3.0.0-alpha2 of PdfBox seems to resolve this problem.