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-streamto 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)