Saving document with attachment using saveIncremental() method saves document without attachment. Although it does work with save() method i.e attachment are embedded in the document
PDFBox Version - 2.0.26
Code:
@Test
public static void testAttachment() throws IOException
{
try (
InputStream sourceStream = new FileInputStream("src/main/resources/sample_doc_usb_signed_2.pdf");
final PDDocument document = PDDocument.load(sourceStream);
)
{
List<String> att_list=List.of("src/main/resources/sample_doc.pdf",
"src/main/resources/sample.docx",
"src/main/resources/text.jpg"
);
final Map<String, PDComplexFileSpecification> embeddedFileMap = new HashMap<>();
for (String attachPath : att_list) {
Path path=Path.of(attachPath);
String mimeType = Files.probeContentType(path);
long size = Files.size(path);
File file = new File(attachPath);
String name = file.getName();
FileInputStream attachStream = new FileInputStream(file);
final PDEmbeddedFile embeddedFile = new PDEmbeddedFile(document, attachStream);
embeddedFile.setSubtype(mimeType);
embeddedFile.setSize((int) size);
embeddedFile.setCreationDate(Calendar.getInstance());
embeddedFile.setModDate(Calendar.getInstance());
//TODO - Encoding
final PDComplexFileSpecification fileSpecification = new PDComplexFileSpecification();
fileSpecification.setFile(name);
fileSpecification.setFileDescription("This is attachment for field and supporting");
fileSpecification.setEmbeddedFile(embeddedFile);
embeddedFileMap.put(name, fileSpecification);
}
final PDEmbeddedFilesNameTreeNode efTree = new PDEmbeddedFilesNameTreeNode();
efTree.setNames(embeddedFileMap);
final PDDocumentNameDictionary names = new PDDocumentNameDictionary(document.getDocumentCatalog());
names.setEmbeddedFiles(efTree);
document.getDocumentCatalog().setNames(names);
//This works
document.save(new FileOutputStream("src/main/resources/sample_wi_attachment.pdf"));
//Does not work - File saved without attachments
// document.saveIncremental(new FileOutputStream("src/main/resources/sample_wi_attachment.pdf"));
}
}
Note: Documents used in above test code are simple PDF
Adding attachments to Signed file (File is not certified) invalidates the signature
private void addAttachment() throws IOException {
//File Signed - not Certified
try(PDDocument document = PDDocument.load(new FileInputStream("src/main/resources/sample-signed_intermediate.pdf"))){
PDDocumentCatalog catalog = document.getDocumentCatalog();
PDDocumentNameDictionary names = catalog.getNames();
PDEmbeddedFilesNameTreeNode efTree = names.getEmbeddedFiles();
Map<String, PDComplexFileSpecification> embeddedFileMap = efTree.getNames();
Set<COSDictionary> objectsToWrite = new HashSet<>();
embeddedFileMap= new HashMap<>();
List<String> att_list=List.of("src/main/resources/sample_doc.pdf",
"src/main/resources/AD23884.docx",
"src/main/resources/text.jpg"
);
for (String attachPath : att_list) {
Path path=Path.of(attachPath);
String mimeType = Files.probeContentType(path);
long size = Files.size(path);
File file = new File(attachPath);
String name = file.getName();
FileInputStream attachStream = new FileInputStream(file);
final PDEmbeddedFile embeddedFile = new PDEmbeddedFile(document, attachStream);
embeddedFile.setSubtype(mimeType);
embeddedFile.setSize((int) size);
embeddedFile.setCreationDate(Calendar.getInstance());
embeddedFile.setModDate(Calendar.getInstance());
//TODO - Encoding
final PDComplexFileSpecification fileSpecification = new PDComplexFileSpecification();
fileSpecification.setFile(name);
fileSpecification.setFileDescription("This is attachment for field and supporting");
fileSpecification.setEmbeddedFile(embeddedFile);
embeddedFileMap.put(name, fileSpecification);
}
efTree.setNames(embeddedFileMap);
names.setEmbeddedFiles(efTree);
document.getDocumentCatalog().setNames(names);
COSDictionary fieldDictionaryEf =efTree.getCOSObject();
while (fieldDictionaryEf != null) {
fieldDictionaryEf.setNeedToBeUpdated(true);
fieldDictionaryEf = (COSDictionary) fieldDictionaryEf.getDictionaryObject(COSName.PARENT);
}
objectsToWrite.add(efTree.getCOSObject());
COSDictionary fieldDictionaryNam =names.getCOSObject();
while (fieldDictionaryNam != null) {
fieldDictionaryNam.setNeedToBeUpdated(true);
fieldDictionaryNam = (COSDictionary) fieldDictionaryNam.getDictionaryObject(COSName.PARENT);
}
objectsToWrite.add(names.getCOSObject());
COSDictionary fieldDictionary =document.getDocumentCatalog().getCOSObject();
while (fieldDictionary != null) {
fieldDictionary.setNeedToBeUpdated(true);
fieldDictionary = (COSDictionary) fieldDictionary.getDictionaryObject(COSName.PARENT);
}
objectsToWrite.add(document.getDocumentCatalog().getCOSObject());
document.saveIncremental(new FileOutputStream("src/main/resources/attachment.pdf"),objectsToWrite);
}
catch (Exception e){
throw e;
}
}