Spring WebFlux: Serve files from controller

Knack :

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();
        }
    }
}
Brian Clozel :

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.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=467666&siteId=1