Как загрузить несколько файлов с помощью Webflux? - PullRequest
0 голосов
/ 14 декабря 2018

Как загрузить несколько файлов с помощью Webflux?

Я отправляю запрос с типом контента: multipart/form-data, и тело содержит одну часть , значение которой представляет собой набор файлов.

Для обработки одного файла я делаю это следующим образом:

Mono<MultiValueMap<String, Part> body = request.body(toMultipartData());
body.flatMap(map -> FilePart part = (FilePart) map.toSingleValueMap().get("file"));

Но как это сделать для нескольких файлов?

PS.Есть ли другой способ загрузить набор файлов в webflux?

Ответы [ 4 ]

0 голосов
/ 06 февраля 2019

Я уже нашел некоторые решения.Предположим, что мы отправляем HTTP-запрос POST с параметром files , который содержит наши файлы.

Примечание: ответы могут быть произвольными

  1. RestController с RequestPart

    @PostMapping("/upload")
    public Mono<String> process(@RequestPart("files") Flux<FilePart> filePartFlux) {
        return filePartFlux.flatMap(it -> it.transferTo(Paths.get("/tmp/" + it.filename())))
            .then(Mono.just("OK"));
    }
    
  2. RestController с ModelAttribute

    @PostMapping("/upload-model")
    public Mono<String> processModel(@ModelAttribute Model model) {
        model.files.forEach(it -> it.transferTo(Paths.get("/tmp/" + it.filename())));
        return Mono.just("OK");
    }
    
    class Model {
        private List<FilePart> files;
        //getters and setters
    }
    
  3. Функциональный способ с HandlerFunction

    public Mono<ServerResponse> upload(ServerRequest request) {
        Mono<String> then = request.multipartData().map(it -> it.get("files"))
            .flatMapMany(Flux::fromIterable)
            .cast(FilePart.class)
            .flatMap(it -> it.transferTo(Paths.get("/tmp/" + it.filename())))
            .then(Mono.just("OK"));
    
        return ServerResponse.ok().body(then, String.class);
    }
    
0 голосов
/ 02 января 2019

Ниже приведен рабочий код для загрузки нескольких файлов с использованием WebFlux.

@RequestMapping(value = "upload", method = RequestMethod.POST)
    Mono<Object> upload(@RequestBody Flux<Part> parts) {

        return parts.log().collectList().map(mparts -> {
            return mparts.stream().map(mmp -> {
                if (mmp instanceof FilePart) {
                    FilePart fp = (FilePart) mmp;
                    fp.transferTo(new File("c:/hello/"+fp.filename()));
                } else {
                    // process the other non file parts
                }
                return mmp instanceof FilePart ? mmp.name() + ":" + ((FilePart) mmp).filename() : mmp.name();
            }).collect(Collectors.joining(",", "[", "]"));
        });

    };
0 голосов
/ 24 января 2019

ключ используется toParts вместо toMultipartData , что проще.Вот пример, который работает с RouterFunctions .

private Mono<ServerResponse> working2(final ServerRequest request) {
    final Flux<Void> voidFlux = request.body(BodyExtractors.toParts())
        .cast(FilePart.class)
        .flatMap(filePart -> {
            final String extension = FilenameUtils.getExtension(filePart.filename());
            final String baseName = FilenameUtils.getBaseName(filePart.filename());
            final String format = LocalDateTime.now().format(DateTimeFormatter.BASIC_ISO_DATE);

            final Path path = Path.of("/tmp", String.format("%s-%s.%s", baseName, format, extension));
            return filePart.transferTo(path);
        });

    return ServerResponse
        .ok()
        .contentType(APPLICATION_JSON_UTF8)
        .body(voidFlux, Void.class);
}
0 голосов
/ 21 декабря 2018

Вы можете перебрать хеш-карту с Flux и вернуть Flux

Flux.fromIterable(hashMap.entrySet())
            .map(o -> hashmap.get(o));

, и она будет отправлена ​​в виде массива с filepart

...