web-dev-qa-db-ja.com

Webfluxを使用して複数のファイルをアップロードする方法

Webfluxを使用して複数のファイルをアップロードする方法

コンテンツタイプmultipart/form-dataでリクエストを送信し、本文に1つのpartが含まれています。この値はファイルのセットです。

単一のファイルを処理するには、次のようにします。

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

しかし、複数のファイルに対してそれを行う方法は?

PS。 webfluxで一連のファイルをアップロードする別の方法はありますか?

15
GVArt

私はすでにいくつかの解決策を見つけました。ファイルを含む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);
    }
    
2
GVArt

Fluxでハッシュマップを反復し、Fluxを返すことができます

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

そして、それはfilepartで配列として送られます

5
Ricard Kollcaku

希望対你有帮助

@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public JSON fileUpload(@RequestPart FilePart file)throws Exception{

    OSS ossClient = new OSSClientBuilder().build(APPConfig.ENDPOINT, APPConfig.ALi_ACCESSKEYID, APPConfig.ALi_ACCESSSECRET);
    File f = null;
    String url;
    try {
        String suffix = file.filename();
        String fileName = "images/" + file.filename();
        Path path = Files.createTempFile("tempimg", suffix.substring(1, suffix.length()));
        file.transferTo(path);
        f = path.toFile();
        ossClient.putObject(APPConfig.BUCKETNAME, fileName, new FileInputStream(f));
        Date expiration = new Date(System.currentTimeMillis() + 3600L * 1000 * 24 * 365 * 10);
        url = ossClient.generatePresignedUrl(APPConfig.BUCKETNAME, fileName, expiration).toString();
    }finally {
        f.delete();
        ossClient.shutdown();
    }
    return JSONUtils.successResposeData(url);
}
0
wjce

キーはtoMultipartDataの代わりにtoPartsを使用することで、より簡単です。 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
nekperu15739