I have a requirement where I need to download a PDF from the website. The PDF needs to be generated within the code, which I thought would be a combination of freemarker and
If you:
byte[]
before sending to the response;InputStream
;@ControllerAdvice
picking up exceptions for you (or not).The code below is what you need:
@RequestMapping(value = "/stuff/{stuffId}", method = RequestMethod.GET)
public ResponseEntity downloadStuff(@PathVariable int stuffId)
throws IOException {
String fullPath = stuffService.figureOutFileNameFor(stuffId);
File file = new File(fullPath);
long fileLength = file.length(); // this is ok, but see note below
HttpHeaders respHeaders = new HttpHeaders();
respHeaders.setContentType("application/pdf");
respHeaders.setContentLength(fileLength);
respHeaders.setContentDispositionFormData("attachment", "fileNameIwant.pdf");
return new ResponseEntity(
new FileSystemResource(file), respHeaders, HttpStatus.OK
);
}
About the file length part: File#length()
should be good enough in the general case, but I thought I'd make this observation because it does can be slow, in which case you should have it stored previously (e.g. in the DB).
Cases it can be slow include: if the file is large, specially if the file is in a remote system or something more elaborated like that - a database, maybe.
InputStreamResource
If your resource is not a file, e.g. you pick the data up from the DB, you should use InputStreamResource. Example:
InputStreamResource isr = new InputStreamResource(new FileInputStream(file));
return new ResponseEntity(isr, respHeaders, HttpStatus.OK);