Upload a File with WebClient – 用WebClient上传文件

最后修改: 2021年 9月 15日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

Our applications often have to handle file uploads via an HTTP request. Since Spring 5, we can now make these requests reactive.
The added support for Reactive Programming allows us to work in a non-blocking way, using a small number of threads and Backpressure.

我们的应用程序经常需要通过HTTP请求来处理文件的上传。从Spring 5开始,我们现在可以使这些请求成为反应式的。
反应式编程的新增支持使我们能够以非阻塞的方式工作,使用少量线程和背压

In this article, we’ll use WebClient – a non-blocking, reactive HTTP client – to illustrate how to upload a file. WebClient is part of the reactive programming library called Project Reactor. We’ll cover two different approaches to uploading a file using a BodyInserter.

在本文中,我们将使用WebClient–一个非阻塞的、反应式 HTTP 客户端–来说明如何上传文件。WebClient是名为Project Reactor的反应式编程库的一部分。我们将介绍使用BodyInserter上传文件的两种不同方法。

2. Uploading a File with WebClient

2.用WebClient上传文件

In order to use WebClient, we’ll need to add the spring-boot-starter-webflux dependency to our project:

为了使用WebClient,我们需要将spring-boot-starter-webflux依赖性添加到我们的项目中。

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

2.1. Uploading a File from a Resource

2.1.从资源中上传文件

To start with, we want to declare our URL:

首先,我们要声明我们的URL。

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

Let’s say in this example we want to upload a PDF. We’ll use MediaType.APPLICATION_PDF as our ContentType.
Our upload endpoint returns an HttpStatus. Since we’re expecting only one result, we’ll wrap it in a Mono:

比方说,在这个例子中,我们想上传一个PDF。我们将使用MediaType.APPLICATION_PDF作为我们的ContentType
我们的上传端点返回一个HttpStatus。因为我们只期待一个结果,我们将把它包装在一个Mono中。

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");
        }
     });

The method consuming this method can also return a Mono, and we can continue until we actually need to access the result. Once we’re ready, we can call the block() method on the Mono object.

消耗这个方法的方法也可以返回一个Mono,我们可以继续下去,直到我们真正需要访问这个结果。一旦我们准备好了,我们就可以调用block()对象上的Mono方法。

The fromResource() method uses the InputStream of the passed resource to write to the output message.

fromResource()方法使用传递的资源的InputStream来写到输出消息。

2.2. Uploading a File from Multipart Resource

2.2.从多部分资源上传文件

If our external upload endpoint takes a Multipart form data, we can use the MultiPartBodyBuilder to take care of the parts:

如果我们的外部上传端点采用多部分表单数据,我们可以使用 MultiPartBodyBuilder来处理这些部分:

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

Here, we could be adding various parts according to our requirements. The value in the map can be an Object or an HttpEntity.

在这里,我们可以根据我们的要求来添加各种部分。地图中的值可以是一个Object或一个HttpEntity.

When we call WebClient, we use BodyInsterter.fromMultipartData and build the object:

当我们调用WebClient时,我们使用BodyInsterter.fromMultipartData并构建对象。

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

We update the content type to MediaType.MULTIPART_FORM_DATA to reflect the changes.

我们将内容类型更新为MediaType.MULTIPART_FORM_DATA以反映这些变化。

Let’s look at the entire call:

让我们来看看整个通话过程。

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. Conclusion

3.总结

In this tutorial, we’ve shown two ways to upload a file with WebClient using BodyInserters. As always, the code is available over on GitHub.

在本教程中,我们展示了使用WebClient上传文件的两种方法,即使用BodyInserters。像往常一样,代码可在GitHub上获得