It seems like it the Spring RestTemplate
isn't able to stream a response directly to file without buffering it all in memory. What is the proper to achieve this using the newer Spring 5 WebClient
?
WebClient client = WebClient.create("https://example.com");
client.get().uri(".../{name}", name).accept(MediaType.APPLICATION_OCTET_STREAM)
....?
I see people have found a few workarounds/hacks to this issue with RestTemplate
, but I am more interested in doing it the proper way with the WebClient
.
There are many examples of using RestTemplate
to download binary data but almost all of them load the byte[]
into memory.
With recent stable Spring WebFlux (5.2.4.RELEASE as of writing):
final WebClient client = WebClient.create("https://example.com");
final Flux<DataBuffer> dataBufferFlux = client.get()
.accept(MediaType.TEXT_HTML)
.retrieve()
.bodyToFlux(DataBuffer.class); // the magic happens here
final Path path = FileSystems.getDefault().getPath("target/example.html");
DataBufferUtils
.write(dataBufferFlux, path, CREATE_NEW)
.block(); // only block here if the rest of your code is synchronous
For me the non-obvious part was the bodyToFlux(DataBuffer.class)
, as it is currently mentioned within a generic section about streaming of Spring's documentation, there is no direct reference to it in the WebClient section.