There are situations when we need to return a downloadable file from a controller method, for example, we might need to return a dynamic pdf generated from db records, or some csv containing records or some processed image etc.
To return a file from the spring controller, you just need to return bytes with appropriate headers. This article will explain how to download a file from a spring controller method.
Let's say have a GET /demo-file-download
end point and we want to return a demo-file.txt
with dynamically created content. Our controller method will look like:
@GetMapping(value = "/demo-file-download")
public ResponseEntity<byte[]> demo() { // (1) Return byte array response
String demoContent = "This is dynamically generated content in demo file"; // (2) Dynamic content
...
}
-
(1) We are returning a byte array response in response to
GET /demo-file-download
. - (2) This is dummy dynamic content, this could be records from db or some calculated data.
We need to set appropriate headers so that browser can handle response properly:
@GetMapping(value = "/demo-file-download")
public ResponseEntity<byte[]> demo() { // (1) Return byte array response
String demoContent = "This is dynamically generated content in demo file"; // (2) Dynamic content
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM_VALUE); // (3) Content-Type: application/octet-stream
httpHeaders.set(HttpHeaders.CONTENT_DISPOSITION, ContentDisposition.attachment().filename("demo-file.txt").build().toString()); // (4) Content-Disposition: attachment; filename="demo-file.txt"
...
}
-
(3) We are setting header
Content-Type: application/octet-stream
. This will set MIME typeapplication/octet-stream
to indicate response contains binary. -
(4) We are also setting header
Content-Disposition: attachment; filename="demo-file.txt"
. This will indicate browser that response is an attachment and it should be saved asdemo-file.txt
Finally, we can send content as bytes in response, the complete controller implementation would look like:
import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpHeaders;
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 DemoController {
@GetMapping(value = "/demo-file-download")
public ResponseEntity<byte[]> demo() { // (1) Return byte array response
String demoContent = "This is dynamically generated content in demo file"; // (2) Dynamic content
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM_VALUE); // (3) Content-Type: application/octet-stream
httpHeaders.set(HttpHeaders.CONTENT_DISPOSITION, ContentDisposition.attachment().filename("demo-file.txt").build().toString()); // (4) Content-Disposition: attachment; filename="demo-file.txt"
return ResponseEntity.ok().headers(httpHeaders).body(demoContent.getBytes()); // (5) Return Response
}
}
-
(5)
demoContent.getBytes()
will returnbyte[]
. The method will return bytes with http headers for browser to download file.
Run the application, hit http://localhost:8080/demo-file-download
in the browser, demo-file.txt
will be downloaded automatically with dummy content in it.
Originally published at: All About Spring Framework
Top comments (0)