springspring-webflux

How to handle Spring WebClient get application/octet-stream as body InputStream?


I am downloading files with a GET request. Some of them are quite large, so I want to get them as a stream and read the bytes in chunks as I can process them, never reading the whole file in memory.

org.springframework.web.reactive.function.client.WebClient seemed like a good fit, but I am running into "UnsupportedMediaTypeException: Content type 'application/octet-stream' not supported.

Here is some short sample code.

@Autowired WebClient.Builder webClientBuilder;
....
ClientResponse clientResponse = webClientBuilder.clientConnector(this.connector)
.build()
.get()
.uri(uri)
.accept(MediaType.APPLICATION_OCTET_STREAM)
.exhange()
.block(Duration.of(1, ChronoUnit.MINUTES));

// blows up here, inside of the body call
InputStream responseInputStream = clientResponse.body(BodyExtractors.toMono(InputStream.class)).block(Duration.of(1, ChronoUnit.MINUTES));

Here is a chunk of the stack trace.

org.springframework.web.reactive.function.UnsupportedMediaTypeException: Content type 'application/octet-stream' not supported
   at org.springframework.web.reactive.function.BodyExtractors.lambda$readWithMessageReaders$20(BodyExtractors.java:254)
   at java.util.Optional.orElseGet(Optional.java:267)
   at org.springframework.web.reactive.function.BodyExtractors.readWithMessageReaders(BodyExtractors.java:250)
   at org.springframework.web.reactive.function.BodyExtractors.lambda$toMono$2(BodyExtractors.java:92)

......

I am on spring-webflux 5.0.7.

I am sure spring webclient must support something beyond JSON. I just don't know how to do that. Help?


Solution

  • Not an expert, but instead of an InputStream, you can get a Flux<byte[]> where each published array will contain a slice of the response body), using

    .get()
    .uri(uri)
    .accept(MediaType.APPLICATION_OCTET_STREAM)
    .retrieve()
    .bodyToFlux(byte[].class)
    

    You can also do the same with ByteBuffer instead of byte[] if you prefer.