Spring Webflux多个文件上传

时间:2019-10-14 12:56:10

标签: java spring spring-webflux

我正在尝试以webflux方式上传一大堆文件。 我无法在服务器和客户端的内存中加载所有文件。 我宁愿不进行多次rest调用,因为我想保持数据传输的状态并在一个文件损坏的情况下将其取消,这就是为什么我要使用webflux的原因(我可能错了)。

我已经测试了很多东西,但是无法使客户端和服务器正常工作(错误的内容类型,解析正文等)。
这是我针对客户端,路由器和服务器处理程序的单元测试的最新版本。 我认为我已经接近使这项工作可行,但我需要您的帮助! 你能帮我吗? 非常感谢!

有我的单元测试:

@Slf4j
@ExtendWith(SpringExtension.class)
@WebFluxTest(FileApiRouter.class)
@Import({FileHandler.class, HttpConfiguration.class})
public class FileControllerTest {

    private static final String DICOM_FILE = "image-000001.dcm";

    @Autowired
    private WebTestClient webTestClient;

    @Autowired
    private HttpConfiguration configuration;

    @MockBean
    private FileService service;

    private void populateHeaders(HttpHeaders headers) {
        headers.set(configuration.getSerieHeader(), "{\"labels\":[\"label1\",\"label2\"]}");
    }

    private MultipartFile fileParts(int i) {
        return new MockMultipartFile("foo"+i, "foo"+i+".txt",
                MediaType.MULTIPART_FORM_DATA_VALUE, "File test content".getBytes());
    }

    @Test
    @DisplayName("[TU] Dicom Http upload filepart")
    public void uploadFile_When1File_Then1String() {

        doReturn(Mono.just("OK")).when(service).storeFilePart(any());

        var dicomFlux = Flux
                .range(0, 3)
                .map(this::fileParts)
                .delayElements(Duration.ofSeconds(1));

        webTestClient.post()
                .uri(FileApiRouter.RESOURCE)
                .headers(this::populateHeaders)
                .contentType(MediaType.MULTIPART_FORM_DATA)
                .body(BodyInserters.fromMultipartAsyncData("dicoms",dicomFlux, MultipartFile.class))
                .exchange()
                .expectStatus()
                .is2xxSuccessful()
                .expectBodyList(String.class)
                .contains("OK","OK","OK")
        ;

    }
}

我的路由器和处理程序:

@Configuration
    public class FileApiRouter {

        public static final String BASE = "/api";
        public static final String V1 = BASE + "/v1";
        public static final String RESOURCE = V1 + "/files";

        private FileHandler  handler;

        public FileApiRouter(FileHandler handler) {
            this.handler = handler;
        }

       @Bean
    public RouterFunction<ServerResponse> postFile() {
        return route(POST(RESOURCE).and(contentType(MediaType.MULTIPART_FORM_DATA)), handler::handleFileParts);
    }


    }


    @Component
    @Slf4j
    public class FileHandler {

        private final FileService service;

        private final HttpConfiguration configuration;

        public FileHandler(FileService service, HttpConfiguration configuration) {
            this.service = service;
            this.configuration = configuration;
        }


        public Mono<ServerResponse> handleFileParts(ServerRequest request) {

        var meta = request.headers().header(configuration.getSerieHeader());
        var then = request
                .body(BodyExtractors.toParts())
                .filter(FilePart.class::isInstance)
                .cast(FilePart.class)
                .flatMap(service::storeFilePart);
        return ServerResponse.ok().body(then, String.class);
    }

    }

0 个答案:

没有答案