For swift file downloads, use Spring'sResponseEntity in your controller. Deliver a ResponseEntity<Resource> with the Content-Disposition header set to "attachment". Use MediaType to specify the MIME type, ensuring the browser treats the file appropriately.
Replace "/path/to/myfile.txt" with your specific file path to make this code snippet ready for use. This sends your file as a downloadable link, named by its original name on the server.
Broadening the Horizon
Serving specific file paths
When working with fluctuating file paths, @PathVariable comes to the rescue:
@GetMapping("/download/{filename:.+}")public ResponseEntity<Resource> downloadFile(@PathVariable String filename){
Resource file = new FileSystemResource("uploads/" + filename);
// Here be dragons 🐉! Make sure the path is safe!return ResponseEntity.ok()
.contentType(MediaType.parseMediaType("application/octet-stream"))
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + file.getFilename() + "\"")
.body(file);
}
Handling Errors like a Boss
Graceful error handling is essential, use @ControllerAdvice for sweeping handling or try-catch blocks for localized issues:
@GetMapping("/download/{filename:.+}")public ResponseEntity<Resource> downloadFile(@PathVariable String filename, HttpServletResponse response){
try {
Resource file = new FileSystemResource("uploads/" + filename);
// Performance art: file juggling 🤹♀️, and check to see if it landed!return ResponseEntity.ok()
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + file.getFilename() + "\"")
.body(file);
} catch (Exception e) {
// Whoops! Error alert 🚨. Log and retreat. response.setStatus(HttpServletResponse.SC_NOT_FOUND);
return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
}
}
Storing Large Files in the Cloud
When streaming huge files, don't bog down memory. Instead, float on cloud 9 with StreamResource and ResourceHttpMessageConverter:
@GetMapping("/download/{filename:.+}")public ResponseEntity<Resource> downloadFileStream(@PathVariable String filename)throws IOException {
Path path = Paths.get("uploads/" + filename);
InputStreamResource resource = new InputStreamResource(Files.newInputStream(path));
// Remember, it's not the size that matters, it's how you use it 😉return ResponseEntity.ok()
.contentLength(Files.size(path))
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.body(resource);
}
Streamlining with Apache Commons IO
Apache Commons IO to the rescue for an elegant way to shuttle bytes between streams:
@GetMapping("/download/{filename:.+}")publicvoiddownloadWithCommonsIO(@PathVariable String filename, HttpServletResponse response)throws IOException {
File file = new File("uploads/" + filename); // so fresh and so clean 🛀 response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"");
try (InputStream is = new FileInputStream(file);
OutputStream os = response.getOutputStream()) {
IOUtils.copy(is, os); // copy-paste like a pro 😎 response.flushBuffer();
}
// Watch out for those IOExceptions! They bite 🦈}
Advanced Solutions
Custom PDF Generation
To serve PDF files, iText might be your knight in shining armor: