1.Tổng quan

Các ứng dụng của bạn thường xuyên phải xử lý các tệp tải lên thông qua yêu cầu HTTP. Kể từ spring 5, chúng ta có thể làm cho các yêu cầu này phản hồi lại.
Hỗ trợ thêm cho Lập trình phản ứng cho phép chúng tôi làm việc theo cách không bị chặn, sử dụng một số lượng nhỏ các luồng và Backpressure.

Trong bài viết này, chúng tôi sẽ sử dụng WebClient - một ứng dụng HTTP phản ứng, không chặn - để minh họa cách tải tệp lên. WebClient là một phần của thư viện lập trình phản ứng được gọi là Project Reactor. Chúng tôi sẽ đề cập đến hai cách tiếp cận khác nhau để tải tệp lên bằng BodyInserter.

2.Tải lên 1 tệp với WebClient

Để sử dụng WebClient, chúng ta sẽ cần thêm phần spring-boot-starter-webflux dependency vào dự án của mình:

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

2.1. Tải File lên từ một nguồn

Để bắt đầu, chúng tôi muốn khai báo URL của mình:

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

Giả sử trong ví dụ này, chúng ta muốn tải lên một tệp PDF. Chúng ta sẽ sử dụng MediaType.APPLICATION_PDF làm ContentType
Điểm cuối tải lên của chúng ta trả về một HttpStatus. Vì chúng ta chỉ mong đợi một kết quả, chúng ta sẽ gói gọn nó trong 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");
        }
     });

Phương thức này cũng có thể trả về Mono và chúng ta có thể tiếp tục cho đến khi chúng ta thực sự cần truy cập kết quả. Khi chúng ta đã sẵn sàng, chúng ta có thể gọi phương thức block () trên đối tượng Mono.

Phương thức fromResource () sử dụng InputStream của tài nguyên được truyền để ghi vào thông báo đầu ra.

2.2. Tải File lên từ nhiều nguồn

Nếu điểm cuối tải lên bên ngoài của chúng ta lấy biểu mẫu dữ liệu Multipart, chúng ta có thể sử dụng MultiPartBodyBuilder để xử lý các phần:

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

Ở đây, chúng ta có thể thêm các phần khác nhau theo các yêu cầu của mình. Giá trị trong map có thể là đối tượng hoặc HttpEntity.

Khi chúng ta gọi WebClient, chúng ta sử dụng BodyInsterter.fromMultipartData và xây dựng đối tượng:

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

Chúng ta cập nhật loại nội dung thành MediaType.MULTIPART_FORM_DATA để phản ánh các thay đổi.

Hãy xem xét toàn bộ quá trình:

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.Kết luận

Trong hướng dẫn này, chúng tôi đã chỉ ra hai cách để tải tệp lên bằng WebClient bằng BodyInserters. Như mọi khi, mã có sẵn trên GitHub.

Tham khảo: https://www.baeldung.com/spring-webclient-upload-file