Reputation: 910
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
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
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