一尘不染

Spring WebFlux:从控制器提供文件

spring-boot

来自.NET和Node,我真的很难弄清楚如何将这种阻塞的MVC控制器转移到非阻塞的WebFlux注释控制器?我已经理解了这些概念,但是没有找到合适的异步Java
IO方法(我希望它返回Flux或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();
        }
    }
}

阅读 263

收藏
2020-05-30

共1个答案

一尘不染

首先,使用Spring MVC实现该目标的方法应如下所示:

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

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

另外,如果您 在没有其他逻辑的情况下 托管这些资源,则可以使用Spring
MVC的静态资源支持。使用Spring
Boot,spring.resources.static-locations可以帮助您自定义位置。

现在,使用Spring WebFlux,您还可以配置相同的spring.resources.static-locations配置属性来提供静态资源。

它的WebFlux版本看起来完全一样。如果您需要执行涉及某些I / O的逻辑,则可以返回a
Mono<Resource>而不是Resource直接返回a ,如下所示:

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

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

请注意,使用WebFlux,如果返回Resource的实际上是磁盘上的文件,我们将利用零复制机制,这将使事情更高效。

2020-05-30