Martin Larizzate
Martin Larizzate

Reputation: 910

HTML render to Downloadable PDF using spring boot and itext

I'm working on a project where i need to use an HTML template to fill some parameters, render it to PDF and finally return it on the response as a download.

At this point as you will see on my service I can generate the final HTML to be rendered. Its fully working.

//bla bla Service code
@Override
    public String buildHtmlFromTemplate(String voucherUUid, Date created, String employerDenomination, String employerEmail) {
        ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
        templateResolver.setSuffix(".html");
        templateResolver.setTemplateMode("HTML");
        templateResolver.setCacheable(false);

        TemplateEngine templateEngine = new TemplateEngine();
        templateEngine.setTemplateResolver(templateResolver);

        Context context = new Context();
        context.setVariable("voucherUuid", voucherUUid);
        context.setVariable("voucherCreated", created);
        context.setVariable("employerDenomination", employerDenomination);
        context.setVariable("employerEmail", employerEmail);

        // Get the plain HTML with the resolved ${name} variable!
        return templateEngine.process("pdf_templates/voucher", context);

    }
//bla bla Service code

Well, reading documentation and obviously with help of stackoverflow y could create these next two methods:

The first one renders the html and generates a file inside the server. I still can not download it.

//bla bla service code
    @Override
    public void generateVoucher(String html) throws IOException, DocumentException {
        OutputStream outputStream = new FileOutputStream("message.pdf");
        ITextRenderer renderer = new ITextRenderer();
        renderer.setDocumentFromString(html);
        renderer.layout();
        renderer.createPDF(outputStream);
        outputStream.close();

    }
//bla bla Service code

With the second one i can download the PDF file but obviously, it is not rendered. So I receive plan HTML inside the PDF.

//bla bla Service code
    @Override
    public ByteArrayOutputStream generateVoucherDocument(String html) throws IOException, DocumentException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        Document document = new Document(PageSize.A4);
        PdfWriter.getInstance(document, bos);
        document.open();
        document.addAuthor("Me");
        document.add(new Paragraph(html));
        document.close();

        return bos;

    }
//bla bla Service code

Itext renderer does not support baos.

This is my Controller code:

@GetMapping("/download")
    public void download(HttpServletResponse response) throws IOException, DocumentException {
        //TODO implementar logica para obtener los datos del voucher
        String htmlInvoice = voucherService.buildHtmlFromTemplate(UUID.randomUUID().toString(), new Date(), "Empleador", "[email protected]");


        ByteArrayOutputStream bos = voucherService.generateVoucherDocument(htmlInvoice);
        byte[] pdfReport = bos.toByteArray();

        String mimeType =  "application/pdf";
        response.setContentType(mimeType);
        response.setHeader("Content-Disposition", String.format("attachment; filename=\"%s\"", "voucherLiquidacion.pdf"));

        response.setContentLength(pdfReport.length);

        ByteArrayInputStream inStream = new ByteArrayInputStream( pdfReport);

        FileCopyUtils.copy(inStream, response.getOutputStream());
    }

I'm really confused in how to render the html inside the PDF and place it to be downloaded. Any Idea?

Upvotes: 0

Views: 4757

Answers (2)

Martin Larizzate
Martin Larizzate

Reputation: 910

Finally I found the solution. As you see on this line at generateVoucher()

renderer.createPDF(outputStream);

I passed an output stream. So, I tried to do the same in generateVoucherDocumentBaos() and it worked.

public ByteArrayOutputStream generateVoucherDocumentBaos(String html) throws IOException, DocumentException {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();

    ITextRenderer renderer = new ITextRenderer();
    renderer.setDocumentFromString(html);
    renderer.layout();
    renderer.createPDF(baos);
    baos.close();

    return baos;

}

Thanks for reading and valoring!

Upvotes: 2

Morteza Asadi
Morteza Asadi

Reputation: 1855

for create a downloadable PDF in user's browser you need to write your report in HttpServletResponse, for example in service layer you write something like this:

public HttpServletResponse generateReport(HttpServletResponse response /*, other args...*/) {
    try {
        response.setContentType("application/pdf");
        response.setHeader("Content-Deposition", "inline; file-name=report.pdf");
        response = reportUtility.generateMyReport(response /*, other args...*/);
    } catch (Exception e) {
        //exception handling....
    }
    return response;
}

and in your resource layer (controller) return it:

@RequestMapping("/download/report")
public ResponseEntity download(HttpServletResponse response) {
    return ResponseEntity.ok(myService.generateReport(response/*, other args...*/));
}

Upvotes: 0

Related Questions