1. 概述
我們的應用程序經常需要通過 HTTP 請求處理文件上傳。自 Spring 5 版本起,我們現在可以對這些請求進行響應式處理。
響應式編程的支持增加了,使我們能夠以非阻塞的方式工作,使用少量線程和背壓。
在本文中,我們將使用 WebClient – 一個非阻塞、響應式 HTTP 客户端 – 來演示如何上傳文件。 WebClient 是響應式編程庫 Project Reactor 的一部分。 我們將涵蓋兩種使用 BodyInserter 上傳文件的不同方法。
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。 我們將使用 MediaType.APPLICATION_PDF 作為我們的 ContentType。
我們的上傳端點返回一個 HttpStatusCode。 由於我們預期只有一個結果,我們將用 Mono 包裝它:
Mono<HttpStatusCode> 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 對象,並且我們可以持續調用它,直到真正需要訪問結果。當準備就緒時,我們可以調用 block() 方法於 Mono 對象上。
fromResource() 方法使用傳入資源的 InputStream 將內容寫入輸出消息。
2.2. 從多部分資源上傳文件
如果我們的外部上傳端點接收多部分表單數據,我們可以使用MultiPartBodyBuilder 來處理各個部分:
MultipartBodyBuilder builder = new MultipartBodyBuilder();
builder.part("file", multipartFile.getResource());在這裏,我們可以根據我們的要求添加各種部分。map中的值可以是Object或HttpEntity
當我們調用WebClient時,我們使用BodyInsterter.fromMultipartData並構建對象:
.body(BodyInserters.fromMultipartData(builder.build()))我們已將內容類型更新為 MediaType.MULTIPART_FORM_DATA,以反映這些更改。
讓我們查看整個調用:
Mono<HttpStatusCode> 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. 結論
在本教程中,我們展示了兩種使用 WebClient 和 BodyInserter 上傳文件的方法。