1. 概要

多くの場合、アプリケーションはHTTPリクエストを介してファイルのアップロードを処理する必要があります。 Spring 5以降、これらのリクエストをリアクティブにすることができます。 リアクティブプログラミングのサポートが追加されたことにより、少数のスレッドとバックプレッシャを使用して、ノンブロッキングの方法で作業できるようになりました。

この記事では、 WebClient –ノンブロッキングのリアクティブHTTPクライアント–を使用して、ファイルをアップロードする方法を説明します。 WebClient は、 ProjectReactorと呼ばれるリアクティブプログラミングライブラリの一部です。 BodyInserterを使用してファイルをアップロードする2つの異なるアプローチについて説明します。

2. WebClientを使用したファイルのアップロード

WebClient を使用するには、プロジェクトに spring-boot-starter-webflux依存関係を追加する必要があります。

<dependency>
    <groupId>org.springframework.boot</groupId>. 
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

2.1. リソースからのファイルのアップロード

まず、URLを宣言します。

URI url = UriComponentsBuilder.fromHttpUrl(EXTERNAL_UPLOAD_URL).build().toUri();

この例では、PDFをアップロードするとします。 ContentTypeとしてMediaType.APPLICATION_PDFを使用します。 アップロードエンドポイントは HttpStatus。  1つの結果のみを期待しているので、それを単核症

Mono<HttpStatus> httpStatusMono = webClient.post()
    .uri(url)
    .contentType(MediaType.APPLICATION_PDF)
    .body(BodyInserters.fromResource(resource))
    .exchangeToMono(response -> {
        if (response.statusCode().equals(HttpStatus.OK)) {
            return response.bodyToMono(HttpStatus.class).thenReturn(response.statusCode());
        } else {
            throw new ServiceException("Error uploading file");
        }
     });

このメソッドを使用するメソッドは、 Mono を返すこともでき、実際に結果にアクセスする必要があるまで続行できます。 準備ができたら、 Monoオブジェクトでblock()メソッドを呼び出すことができます。

fromResource()メソッドは、渡されたリソースの InputStream を使用して、出力メッセージに書き込みます。

2.2. マルチパートリソースからのファイルのアップロード

外部アップロードエンドポイントがマルチパートフォームデータを取得する場合、 MultiPartBodyBuilder を使用してパーツを処理できます:

MultipartBodyBuilder builder = new MultipartBodyBuilder();
builder.part("file", multipartFile.getResource());

ここでは、要件に応じてさまざまなパーツを追加できます。 マップの値は、ObjectまたはHttpEntity。にすることができます。

WebClient を呼び出すときは、 BodyInsterter.fromMultipartData を使用して、オブジェクトをビルドします。

.body(BodyInserters.fromMultipartData(builder.build()))

コンテンツタイプをMediaType.MULTIPART_FORM_DATAに更新して、変更を反映します。

呼び出し全体を見てみましょう:

Mono<HttpStatus> httpStatusMono = webClient.post()
    .uri(url)
    .contentType(MediaType.MULTIPART_FORM_DATA)
    .body(BodyInserters.fromMultipartData(builder.build()))
    .exchangeToMono(response -> {
        if (response.statusCode().equals(HttpStatus.OK)) {
            return response.bodyToMono(HttpStatus.class).thenReturn(response.statusCode());
        } else {
            throw new ServiceException("Error uploading file");
        }
      });

3. 結論

このチュートリアルでは、BodyInserterを使用してWebClientでファイルをアップロードする2つの方法を示しました。 いつものように、コードはGitHubから入手できます。