Downloading a File from Spring Controllers

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



Leave a reply



Submit