Downloading a file from spring controllers
@RequestMapping(value = "/files/{file_name}", method = RequestMethod.GET)
public void getFile(
@PathVariable("file_name") String fileName,
HttpServletResponse response) {
try {
// get your file as InputStream
InputStream is = ...;
// copy it to response's OutputStream
org.apache.commons.io.IOUtils.copy(is, response.getOutputStream());
response.flushBuffer();
} catch (IOException ex) {
log.info("Error writing file to output stream. Filename was '{}'", fileName, ex);
throw new RuntimeException("IOError writing file to output stream");
}
}
Generally speaking, when you have response.getOutputStream()
, you can write anything there. You can pass this output stream as a place to put generated PDF to your generator. Also, if you know what file type you are sending, you can set
response.setContentType("application/pdf");
download a file from Spring boot rest service
Option 1 using an InputStreamResource
Resource implementation for a given InputStream.
Should only be used if no other specific Resource implementation is > applicable. In particular, prefer ByteArrayResource or any of the file-based Resource implementations where possible.
@RequestMapping(path = "/download", method = RequestMethod.GET)
public ResponseEntity<Resource> download(String param) throws IOException {
// ...
InputStreamResource resource = new InputStreamResource(new FileInputStream(file));
return ResponseEntity.ok()
.headers(headers)
.contentLength(file.length())
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.body(resource);
}
Option2 as the documentation of the InputStreamResource suggests - using a ByteArrayResource:
@RequestMapping(path = "/download", method = RequestMethod.GET)
public ResponseEntity<Resource> download(String param) throws IOException {
// ...
Path path = Paths.get(file.getAbsolutePath());
ByteArrayResource resource = new ByteArrayResource(Files.readAllBytes(path));
return ResponseEntity.ok()
.headers(headers)
.contentLength(file.length())
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.body(resource);
}
Download large file through spring mvc controller
In order to download the file I would do the following:
- create a temp CSV file
- download the file
In order to do it I would write this kind of controller:
@RequestMapping(method = { RequestMethod.GET }, value = { "/downloadCsv" })
public ResponseEntity<InputStreamResource> downloadCSV()
{
try
{
String fileName = "test.csv";
//Create here your CSV file
File theCsv = new File(fileName);
HttpHeaders respHeaders = new HttpHeaders();
MediaType mediaType = new MediaType("text","csv");
respHeaders.setContentType(mediaType);
respHeaders.setContentDispositionFormData("attachment", fileName);
InputStreamResource isr = new InputStreamResource(new FileInputStream(theCsv));
return new ResponseEntity<InputStreamResource>(isr, respHeaders, HttpStatus.OK);
}
catch (Exception e)
{
String messagge = "Error in CSV creation; "+e.getMessage();
logger.error(messagge, e);
return new ResponseEntity<InputStreamResource>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
By using this kind of controller I'm able in downloading very huge files
Angelo
Spring : Download file from REST controller
I modify the 'download' method with stream and it works correctly like I want.
public void download(Integer id, HttpServletResponse response){
Line line = getById(Line.class, id);
InputStream is = line.getFile().getBinaryStream;
IOUtils.copy(is, response.getOutputStream());
response.flushBuffer();
}
And my controller was like that :
public ResponseEntity<?> download(@RequestParam("id") Integer id, HttpServletResponse response)
{
lineService.download(id,response);
return new ResponseEntity<>(HttpStatus.OK);
}
Spring Web: Download a File from a service via a Spring Service
Turns out I was missing this annotation parameter in my *Controller class:
produces = MediaType.APPLICATION_OCTET_STREAM_VALUE
The whole method of the controller should look like this:
@RequestMapping(value = "/download/{type}/{id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
public ResponseEntity<?> downloadReport(@PathVariable String type, @PathVariable String id) throws Exception {
return new ResponseEntity<>(reportService.downloadReport(type, id), HttpStatus.OK);
}
Can Spring Boot set the name of a file being downloaded from a controller endpoint?
Please try this, comments inline:
package com.example;
import java.io.IOException;
import java.security.Principal;
import java.util.Date;
import org.apache.commons.io.IOUtils;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class SomeController {
@GetMapping(
value = "/get-image-with-media-type",
produces = MediaType.IMAGE_JPEG_VALUE
) // we can inject user like this (can be null, when not secured):
public ResponseEntity<byte[]> getImageWithMediaType(Principal user) throws IOException {
// XXXResource is the "spring way", FileSystem- alternatively: ClassPath-, ServletContext-, ...
FileSystemResource fsr = new FileSystemResource("/path/to/some/image.jpg");
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.set(HttpHeaders.CONTENT_DISPOSITION,
// for direct downlad "inline", for "save as" dialog "attachment" (browser dependent)
// filename placeholders: %1$s: user id string, 2$tY: year 4 digits, 2$tm: month 2 digits, %2$td day of month 2 digits
String.format("inline; filename=\"%1$s-%2$tY-%2$tm-%2$td-image.jpg\"",
// user name, current (server) date:
user == null ? "anonymous" : user.getName(), new Date()));
// and fire:
return new ResponseEntity<>(
IOUtils.toByteArray(fsr.getInputStream()),
responseHeaders,
HttpStatus.OK
);
}
}
Relevant reference:
- Method Arguments(Principal)
- Formatter
- ResponseEntity(+ headers sample)
- RFC2616 (Section 19.5.1 Content-Disposition)
With ContentDisposition
it can look (just) like:
responseHeaders.setContentDisposition(
ContentDisposition
.inline()// or .attachment()
.filename(// format file name:
String.format(
"%1$s-%2$tY-%2$tm-%2$td-image.jpg",
user == null ? "anonymous" : user.getName(),
new Date()
)
)
.build()
);
TYVM: How to set 'Content-Disposition' and 'Filename' when using FileSystemResource to force a file download file?
Spring Controller download file from file system restriction
Path tmpPath = Paths.get("/tmp/"); //valid directory
String fileName = "foo/bar.xls"; //supplied fileName
Path filePath = tmpPath.resolve(fileName); //add fileName to path
Path fileParent = filePath.getParent(); //get parent directory
System.out.println(fileParent);
System.out.println(tmpPath.equals(fileParent)); //false because fileParent is '/tmp/foo'
'tmpPath' will be equals 'fileParent' if you supply a valid fileName like 'bar.xls'.
I think you can also simplify the extension checking: filePath.endsWith(".xls");
should be enough. And don't concatenate file paths ("/tmp/" + fileName). Paths.get("/tmp", fileName) will do that for you.
Related Topics
What Is a Nosuchbeandefinitionexception and How to Fix It
What Are Functional Interfaces Used For in Java 8
Calendar Date to Yyyy-Mm-Dd Format in Java
How to Efficiently Remove Duplicates from an Array Without Using Set
Including Jars in Classpath on Commandline (Javac or Apt)
How to Use Scanner to Accept Only Valid Int as Input
Intersection and Union of Arraylists in Java
How Many Significant Digits Do Floats and Doubles Have in Java
How Many Characters Can a Java String Have
Restricting Jtextfield Input to Integers
"Loop:" in Java Code. What Is This, and Why Does It Compile
Equals VS Arrays.Equals in Java