0

I'm currently working on an api which generate a pdf file with some customer report and contain some pdf atatchments related to the report. I am adding an attachment to the PDF using PDFBox library in Java by referring to the code snippet, Adding a File Attachment

I successfully attached the document created using ByteArrayInputStream to the attachment. However, when I try to open the attachment in the document using Adobe reader or any PDF viewer tool I am getting the error as in the screenshot. enter image description here

If I use the ef.setSubtype("text/plain") and file extension as '.txt' I am able to open the attachment successfully. The code snippet I used is as below,

@GetMapping("/generate-pdf")
public ResponseEntity<InputStreamResource> generatePDFWithAttachment() {
    try {
        final PDDocument doc = new PDDocument();
        PDPage page = new PDPage();
        doc.addPage(page);

        PDPageContentStream contentStream = new PDPageContentStream(doc, page);

        contentStream.beginText();
        contentStream.setFont(PDType1Font.HELVETICA, 15);
        contentStream.newLineAtOffset(100, 700);
        contentStream.setNonStrokingColor(Color.red);
        contentStream.showText("Go to Document -> File Attachments to View Embedded Files");

        Map<String, String> keyValueMap = new HashMap<>();
        keyValueMap.put("file1.pdf", "test element 1");
        keyValueMap.put("file2.pdf", "test element 2");

        //------- start attachment section
        // embedded files are stored in a named tree
        // create a new tree node and add the embedded file
        PDEmbeddedFilesNameTreeNode efTree = new PDEmbeddedFilesNameTreeNode();
        Map<String, PDComplexFileSpecification> treeNodeMap = new HashMap<>();

        for (Map.Entry<String, String> entry : keyValueMap.entrySet()) {

            // first create the file specification, which holds the embedded file
            PDComplexFileSpecification fs = new PDComplexFileSpecification();
            fs.setFile(entry.getKey());
            // create a dummy file stream, this would probably normally be a FileInputStream
            byte[] data = entry.getValue().getBytes();
            ByteArrayInputStream fakeFile = new ByteArrayInputStream(data);
            // now lets some of the optional parameters
            PDEmbeddedFile ef = new PDEmbeddedFile(doc, fakeFile);
            ef.setSubtype("application/pdf");
            ef.setSize(data.length);
            ef.setCreationDate(Calendar.getInstance());
            fs.setEmbeddedFile(ef);
            treeNodeMap.put(entry.getKey(), fs);
        }

        efTree.setNames(treeNodeMap);
        PDDocumentNameDictionary names = new PDDocumentNameDictionary(doc.getDocumentCatalog());
        names.setEmbeddedFiles(efTree);
        doc.getDocumentCatalog().setNames(names);
        //------- end attachment section
        contentStream.endText();

        contentStream.close();
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        doc.save(outputStream);
        doc.close();
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_PDF);
        headers.setContentDispositionFormData("attachment", "sample.pdf");

        InputStreamResource resource = new InputStreamResource(new ByteArrayInputStream(outputStream.toByteArray()));

        return ResponseEntity.ok()
                .headers(headers)
                .body(resource);


    } catch (IOException e) {
        System.err.println("Exception while trying to create pdf document - " + e);
    }
    return null;
}

I assume attachments can contain file of type .pdf. I also tried by providing the charset parameter to UTF_8 byte[] data = entry.getValue().getBytes(StandardCharsets.UTF_8); and that also didn't helps

Rosa Mystica
  • 243
  • 1
  • 3
  • 17
  • "test element 1" isn't a PDF, that's still a text file even if you use "application/pdf". The PDF format starts with "%PDF" and then lots of complex stuff. – Tilman Hausherr Jun 09 '23 at 18:50
  • "test element 1" is a text I want to display as a content inside the attachment file1.pdf of type 'application/pdf" type. I am trying to convert that content and adding that to PDEmbeddedFile . If the current one is not the approach could you please advise how to add an attachment with some content I fetched from DB inside an attachment of type 'application/pdf' – Rosa Mystica Jun 09 '23 at 19:08
  • Create a real PDF that has this text formatted in the way you want, save this PDF to a ByteArrayOutputStream, and use this data. You can use the TextToPDF command line utility if you don't want to handle topics like line breaks and page breaks. – Tilman Hausherr Jun 10 '23 at 02:22
  • @TilmanHausherr if that is the case do we need two types of functions one for handling the 'text/plain' and other for handling 'applicatiin/pdf'. Is there a common function or helper class in pdfBox which can handle both this cases with a common logic. – Rosa Mystica Jun 10 '23 at 10:36
  • I still don't understand you, if you want to create a text sometimes and a PDF sometimes, then you'll have to write two different functions, but at the end both should end as a byte stream. – Tilman Hausherr Jun 11 '23 at 02:53

0 Answers0