Downloading a file from spring controller with spring boot

Spring file downloader code with example
Spring file downloader code with example

Sometimes, we will have to provide rest API endpoint for downloading certain files. In this article, we will see how to provide an option to download any file from a java spring rest API controller, with example code snippet. We will use spring-boot annotations here to make things easier and straightforward. This method provides the file download option with resume support.

Configure a file for download with spring controller

Let’s assume that you have a file that you want to provide for download at “data/file_to_download.mp4”. Then you can write the controller as follows to make it downloadable by any browser. Also, the REST API endpoint is given in the @GetMapping annotation.

@GetMapping(path = "/your-api/get-video-file")
public ResponseEntity<Resource> downloadFile() throws Exception {
    File downloadFile = new File("data/file_to_download.mp4");
    InputStreamResource resource = new InputStreamResource(new FileInputStream(downloadFile));
    HttpHeaders header = new HttpHeaders();
    header.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + downloadFile.getName());
    header.add("Cache-Control", "no-cache, no-store, must-revalidate");
    header.add("Pragma", "no-cache");
    header.add("Expires", "0");
    return ResponseEntity.ok()
        .headers(header)
        .contentLength(downloadFile.length())
        .contentType(MediaType.parseMediaType("application/octet-stream"))
        .body(resource);
}

The “application/octet-stream” media type is useful for providing the file as a raw type. The HttpHeader provides information about the file metadata, including the size of the file so that the browser can properly determine its size and create a proper download progress bar.

Providing spring boot file download based on GET parameter

Now, let’s say you want to provide multiple files for download and don’t want to write separate functions for each. In this case, you can simply accept the name of the file to be downloaded as a request parameter and use it to process the file downloading. Let’s see how this can be done in the following code snippet.

Firefox download dialog from the spring boot file download link

@GetMapping(path = "/your-api/download-file")
public ResponseEntity<Resource> downloadBenchmarkFile10Mb(@RequestParam("file-name") String fileName) throws Exception {
  File downloadFile = new File(fileName);
  //Return 404 error if the file is not found
  if (!downloadFile.exists()) {
    return ResponseEntity.noContent()
        .build();
  }
  InputStreamResource resource = new InputStreamResource(new FileInputStream(downloadFile));
  HttpHeaders header = new HttpHeaders();
  header.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + downloadFile.getName());
  header.add("Cache-Control", "no-cache, no-store, must-revalidate");
  header.add("Pragma", "no-cache");
  header.add("Expires", "0");
  header.add("hash", FileUtil.createFileHash(downloadFile));
  return ResponseEntity.ok()
      .headers(header)
      .contentLength(downloadFile.length())
      .contentType(MediaType.parseMediaType("application/octet-stream"))
      .body(resource);
}

Here, the file-name to be downloaded will be taken as an argument from the GET request and then will be used for resolving the file. If such a file is not available, then a 404 response will be returned, as you can see in the code comment. To download from the following REST GET endpoint, you can make a request as follows.

https://yourserver/your-api/download-file?file-name=zulu.tar.gz

That’s all about spring boot file download

Muhammed Afsal Villan
Muhammed Afsal Villan is an experienced full-stack developer, specialized in desktop and mobile application development. He also regularly publishes quality tutorials on his YouTube channel named 'Genuine Coder'. He likes to contribute to open-source projects and is always enthusiastic about new technologies.

3 COMMENTS