Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring WebFlux: Serve files from controller

Coming from .NET and Node I really have a hard time to figure out how to transfer this blocking MVC controller to a non-blocking WebFlux annotated controller? I've understood the concepts, but fail to find the proper async Java IO method (which I would expect to return a Flux or Mono).

@RestController
@RequestMapping("/files")
public class FileController {

    @GetMapping("/{fileName}")
    public void getFile(@PathVariable String fileName, HttpServletResponse response) {
        try {
            File file = new File(fileName);
            InputStream in = new java.io.FileInputStream(file);
            FileCopyUtils.copy(in, response.getOutputStream());
            response.flushBuffer();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
like image 225
Knack Avatar asked Mar 13 '18 14:03

Knack


People also ask

Can I use Springmvc and WebFlux together?

There are several reasons for this: Spring MVC can't run on Netty. both infrastructure will compete for the same job (for example, serving static resources, the mappings, etc) mixing both runtime models within the same container is not a good idea and is likely to perform badly or just not work at all.

How do I use WebFlux spring?

Running the Spring WebFlux Spring Boot App If you have Spring support in Eclipse, then you can run above class as Spring Boot App. If you like to use command line, then open terminal and run command mvn spring-boot:run from the project source directory.

What is WebFlux spring5?

Overview. Spring 5 includes Spring WebFlux, which provides reactive programming support for web applications. In this tutorial, we'll create a small reactive REST application using the reactive web components RestController and WebClient. We'll also look at how to secure our reactive endpoints using Spring Security.


1 Answers

First, the way to achieve that with Spring MVC should look more like this:

@RestController
@RequestMapping("/files")
public class FileController {

    @GetMapping("/{fileName}")
    public Resource getFile(@PathVariable String fileName) {
        Resource resource = new FileSystemResource(fileName);        
        return resource;
    }
}

Also, not that if you just server those resources without additional logic, you can use Spring MVC's static resource support. With Spring Boot, spring.resources.static-locations can help you customize the locations.

Now, with Spring WebFlux, you can also configure the same spring.resources.static-locations configuration property to serve static resources.

The WebFlux version of that looks exactly the same. If you need to perform some logic involving some I/O, you can return a Mono<Resource> instead of a Resource directly, like this:

@RestController
@RequestMapping("/files")
public class FileController {

    @GetMapping("/{fileName}")
    public Mono<Resource> getFile(@PathVariable String fileName) {
        return fileRepository.findByName(fileName)
                 .map(name -> new FileSystemResource(name));
    }
}

Note that with WebFlux, if the returned Resource is actually a file on disk, we will leverage a zero-copy mechanism that will make things more efficient.

like image 76
Brian Clozel Avatar answered Sep 25 '22 05:09

Brian Clozel