Return Generated PDF Using Spring MVC

Return generated pdf using spring MVC

You were on the right track with response.getOutputStream(), but you're not using its output anywhere in your code. Essentially what you need to do is to stream the PDF file's bytes directly to the output stream and flush the response. In Spring you can do it like this:

@RequestMapping(value="/getpdf", method=RequestMethod.POST)
public ResponseEntity<byte[]> getPDF(@RequestBody String json) {
// convert JSON to Employee
Employee emp = convertSomehow(json);

// generate the file
PdfUtil.showHelp(emp);

// retrieve contents of "C:/tmp/report.pdf" that were written in showHelp
byte[] contents = (...);

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_PDF);
// Here you have to set the actual filename of your pdf
String filename = "output.pdf";
headers.setContentDispositionFormData(filename, filename);
headers.setCacheControl("must-revalidate, post-check=0, pre-check=0");
ResponseEntity<byte[]> response = new ResponseEntity<>(contents, headers, HttpStatus.OK);
return response;
}

Notes:

  • use meaningful names for your methods: naming a method that writes a PDF document showHelp is not a good idea
  • reading a file into a byte[]: example here
  • I'd suggest adding a random string to the temporary PDF file name inside showHelp() to avoid overwriting the file if two users send a request at the same time

Return a PDF file with Spring MVC

That would be like the below:

@Controller
@RequestMapping("/generateReport.do")
public class ReportController

@RequestMapping(method = RequestMethod.POST)
public void generateReport(HttpServletResponse response) throws Exception {

byte[] data = //read PDF as byte stream

streamReport(response, data, "my_report.pdf"));
}

protected void streamReport(HttpServletResponse response, byte[] data, String name)
throws IOException {

response.setContentType("application/pdf");
response.setHeader("Content-disposition", "attachment; filename=" + name);
response.setContentLength(data.length);

response.getOutputStream().write(data);
response.getOutputStream().flush();
}
}

How to download pdf file and redirect to home page in Spring mvc

Just to get the pdf (download into browser from local file system), this code is sufficient:

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@RequestMapping("/admin/generate_pdf")
public class PdfController {

@GetMapping(value = "/online", /*this is "nice to have" ->*/ produces = MediaType.APPLICATION_PDF_VALUE)
@ResponseBody // this is important, as the return type byte[]
public byte[] generating_pdf() throws IOException {//exception handling...
System.out.println("hello");//logging
// re-generate new file if needed (thread-safety!)...
// ..and dump the content as byte[] response body:
return Files.readAllBytes(Paths.get("d:\\sanjeet7.pdf"));
}
}

... if you need "a refresh", you can "rewrite" the file/re-call your service, but still maybe not the "thread-safest" solution.

Edit: With no further configuration (port/context root/...), You should reach this at: http://localhost:8080/admin/generate_pdf/online


If you want to "operate closer to the bytes" and with void return type/no @ResponseBody and want an additional redirect (to be tested), I think this should still work:

@Controller
public class ... {

@GetMapping(value = ..., produces ...)
//no request body, void return type, response will be autowired and can be handled
public void generatePdf(javax.servlet.http.HttpServletResponse response) throws ... {
java.io.OutputStream outStr = response.getOutputStream();
// dump from "somewhere" into outStr, "finally" close.
outStr.close();
//TO BE TESTED:
response.sendRedirect("/");
}
}

..or even (return a "view name" + operate on outputStream):

   @GetMapping(value = ..., produces = "application/pdf")
//return a "view name" (!), and you can inject (only) the outputstream (without enclosing response)
public String generatePdf(java.io.OutputStream outputstream) throws... {
// ... do your things on outputstream, IOUtils is good...
// close the stream(?)
// ..and
return "redirect:/"; // to a redirect or a view name.
// .... (in a "spring way", which could also save you some "context path problems"
} ...

Return generated pdf using spring MVC With angularjs

You can use

headers.setContentType(MediaType.parseMediaType("application/pdf;charset=utf-8"));

Spring MVC pdf generation

tldr; you should be able to use a view and save it to a file.

Try using Flying Saucer and its iTextRenderer when you overload AbstractPdfView.

import org.xhtmlrenderer.pdf.ITextRenderer;
public class MyAbstractView extends AbstractView {
OutputStream os;

public void buildPdfDocument(Map<String,Object> model, com.lowagie.text.Document document, com.lowagie.text.pdf.PdfWriter writer, HttpServletRequest request, HttpServletResponse response){
//process model params
os = new FileOutputStream(outputFile);
ITextRenderer renderer = new ITextRenderer();
String url = "http://www.mysite.com"; //set your sample url namespace here
renderer.setDocument(document, url); //use the passed in document
renderer.layout();
renderer.createPDF(os);
os.close();
}
}

protected final void renderMergedOutputModel(Map<String,Object> model,
HttpServletRequest request,
HttpServletResponse response)
throws Exception{
if(os != null){
response.outputStream = os;
}

public byte[] getPDFAsBytes(){
if(os != null){
byte[] stuff;
os.write(stuff);
return stuff;
}
}

}

You'll probably have to tweak the sample implementation shown here, but that should provide a basic gist.



Related Topics



Leave a reply



Submit