Spring WebFlux File download example

In this tutorial, I will show you File download using Spring WebFlux example.

This Spring Boot App works with:
Angular 8 / Angular 10 / Angular 11 / Angular 12 / Angular 13 / Angular 14 / Angular 15
Angular Material 12
Vue Client / Vuetify Client
React Client / React Hooks Client
React Image Upload with Preview
Material UI Client
Axios Client

Related Posts:
Spring Boot Delete File example
Spring Boot WebFlux Rest API example
Spring Boot Thymeleaf File Upload example
How to upload multiple files in Java Spring Boot
Spring Boot Upload/Download File to/from Database example
Spring Boot: Upload/Import Excel file data into MySQL Database
Spring Boot: Upload/Import CSV file data into MySQL Database
– Documentation: Spring Boot Swagger 3 example
– Caching: Spring Boot Redis Cache example

Deployment: Deploy Spring Boot App on AWS – Elastic Beanstalk


Spring WebFlux File download example Overview

Our Spring Boot Reactive Web – WebFlux File Upload Application will provide API for downloading File from server with the url link.

Here is the API to be exported:

Methods Urls Actions
GET /files/[filename] download a File

This is the static folder that stores all uploaded files:

spring-webflux-file-download-example-folder

For deleting file, kindly visit:
Spring Boot Delete File example

Technology

  • Java 17/11
  • Spring Boot 3/2 (with Spring WebFlux)
  • Maven 3.6.1

Setup Spring Boot project

Open pom.xml and add WebFlux dependency:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

Create Service for File Download

service/FileStorageService.java

package com.bezkoder.spring.webflux.file.service;

import java.net.MalformedURLException;
import java.nio.file.Path;
import java.nio.file.Paths;

import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.stereotype.Service;

import reactor.core.publisher.Flux;

@Service
public class FileStorageService {

  private final Path root = Paths.get("uploads");

  @Override
  public Flux<DataBuffer> load(String filename) {
    try {
      Path file = root.resolve(filename);
      Resource resource = new UrlResource(file.toUri());

      if (resource.exists() || resource.isReadable()) {
        return DataBufferUtils.read(resource, new DefaultDataBufferFactory(), 4096);
      } else {
        throw new RuntimeException("Could not read the file!");
      }
    } catch (MalformedURLException e) {
      throw new RuntimeException("Error: " + e.getMessage());
    }
  }
}

Firstly, we read the file content as a Resource.

Then if the resource exists, we create a Flux of DataBuffer from the file content using DataBufferUtils class, and set a buffer size of 4096 bytes. You can adjust the buffer size depending on your use case.

Create Controller for WebFlux File download

In controller package, we create FileController.

controller/FileController.java

package com.bezkoder.spring.webflux.file.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.buffer.DataBuffer;
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.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

import com.bezkoder.spring.webflux.file.service.FileStorageService;

import reactor.core.publisher.Flux;

@Controller
@CrossOrigin("http://localhost:8081")
public class FileController {
  @Autowired
  FileStorageService storageService;

  @GetMapping("/files/{filename:.+}")
  public ResponseEntity<Flux<DataBuffer>> getFile(@PathVariable String filename) {
    Flux<DataBuffer> file = storageService.load(filename);

    return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + filename + "\"")
        .contentType(MediaType.APPLICATION_OCTET_STREAM).body(file);
  }
}

@CrossOrigin is for configuring allowed origins.
@Controller annotation is used to define a controller.
@GetMapping annotation is for mapping HTTP GET /files/[filename] requests onto getFile() method.

– We use @Autowired to inject implementation of FileStorageService bean to local variable.
– Then use FileStorageService‘s load() method to create a Flux of DataBuffer from the file, and use the body() method of ResponseEntity to write the file content to the response.
– We also use body() and contentType() method to set the file name and content type in the response headers.

Source Code

You can find the complete source code for this tutorial on Github.

With Template Engine:
Spring Boot Thymeleaf File Upload/Download example

Conclusion

Today we’ve learned how to create Spring Boot example – Spring WebFlux File Download from a static folder.

Following tutorials explain how to build Front-end Apps to work with our Spring Boot Server:
Angular 8 / Angular 10 / Angular 11 / Angular 12 / Angular 13 / Angular 14 / Angular 15
Angular Material 12
Vue Client / Vuetify Client
React Client / React Hooks Client
React Image Upload with Preview
Material UI Client
Axios Client

For deleting file:
Spring Boot Delete File example

You can also know way to download an Excel/CSV file from database with the post:
Spring Boot Download Excel file from Database example
Spring Boot Download CSV file from Database example

If you want to store files in database like this:
spring-boot-upload-files-to-database-table-files

You can find instruction at:
Spring Boot Upload/Download File to/from Database example

Happy Learning! See you again.

Further Reading