5

I'm supposed to download a ZIP file from 3rd party API. However, when I'm using Spring Webclient I end up with an empty file. Any ideas what I'm doing wrong? What is the proper way to store the content of Flux<DataBuffer> to a file?

Here's my code:

WebClient client = WebClient.builder()
            .clientConnector(new ReactorClientHttpConnector(httpClient1))
            .baseUrl(String.format(FILE_DOWNLOAD_PATH))
            .build();


    WebClient.RequestBodyUriSpec method = client.method(HttpMethod.GET);
    method.header("Authorization", "Bearer " + accessToken);
    final Flux<DataBuffer> dataBufferFlux = method.retrieve().bodyToFlux(DataBuffer.class);

    final Path path = FileSystems.getDefault().getPath("example" + new Random(200).nextInt() + ".zip");

    WritableByteChannel channel = Files.newByteChannel(path, StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE);
    Mono<Path> then = DataBufferUtils.write(dataBufferFlux, channel)
            .map(DataBufferUtils::release)
            .then(Mono.just(path));

UPDATE: The above code is being called directly from main, and then the application shuts down. Could this be an issue?

Endrew
  • 157
  • 1
  • 2
  • 12
  • If that don't throw an exception, the problem is the REST Api you are calling – Adrian Lagartera Jul 14 '20 at 15:08
  • @AL it doesn't throw an exception, it just creates an empty .zip file. I'm able to download the file from this API using POSTMAN, so the API itself works just fine – Endrew Jul 14 '20 at 15:25
  • 1
    As for your update - remember that nothing happens until you subscribe. Usually with spring the framework will subscribe for you, but obviously that doesn't apply if you're not using a framework controlled method. Try calling `block()` on your `then` variable. – Michael Berry Jul 14 '20 at 17:15
  • Hey @Endrew .It's been quite a while since you posted this question. Any updates from your side? Did you try out the answer I provided ? – Abhinaba Chakraborty Jul 22 '20 at 16:33

1 Answers1

8

As @MichaelBerry mentioned, you are missing the block call.

It is clearly mentioned in the method documentation that:

Note that the writing process does not start until the returned Flux is subscribed to.

Below code worked for me:

public class MySpringBootApp {

  public static void main(String[] args) throws IOException {

    Path path = Paths.get("src/main/resources/sample.zip");
    WebClient client = WebClient.builder()
        .baseUrl("https://www.learningcontainer.com/wp-content/uploads/2020/05/sample-zip-file.zip")
        .build();
    Flux<DataBuffer> dataBufferFlux = client.get().retrieve().bodyToFlux(DataBuffer.class);
    DataBufferUtils.write(dataBufferFlux, path, StandardOpenOption.CREATE).block(); //Creates new file or overwrites exisiting file

  }


}
Abhinaba Chakraborty
  • 3,488
  • 2
  • 16
  • 37