title: Resume file downloading with Spring Webflux and static files serving in Spring
body: <p>I belive there is no answear in the whole internet for this as it is probably very complex but I will go ahead and ask.</p>
  
  <p>Basically, I want to have a cross communication between multiple Spring applications. Each of them is serving resources in a static way, <a href="https://www.baeldung.com/spring-mvc-static-resources" rel="nofollow noreferrer">here is the link for that topic</a>. This serving is capitalized by other application instances that can download those files on request (for now I am transferring files via HTTP). I was able to download files thanks to the <a href="https://stackoverflow.com/questions/50091069/downlolad-and-save-file-from-clientrequest-using-exchangefunction-in-project-rea">Downlolad and save file from ClientRequest using ExchangeFunction in Project Reactor</a> SO question.</p>
  
  <p>Right now I want to elevate my code so that in case of the connection issue or application being temporarily unavailable for the given timeout I am able to <strong>resume</strong> the downloading of the file. I configured the <code>WebClient</code> timeouts as in <a href="https://medium.com/@senanayake.kalpa/configuring-timeouts-in-spring-reactive-webclient-4bc5faf56411" rel="nofollow noreferrer">this article</a>.</p>
  
  <p>Right now, I thought that such code would actually let me handle temporarily unavailable services:</p>
  
  <pre><code>final AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(targetPath, StandardOpenOption.WRITE);
  
  Flux&lt;DataBuffer&gt; fileData = Mono.just(filePath)
      .map(file -&gt; targetPath.toFile().exists() ? targetPath.toFile().length() : 0)
      .map(bytes -&gt; webClient
              .get()
              .uri(uri)
              .accept(MediaType.APPLICATION_OCTET_STREAM)
              .header("Range", String.format("bytes=%d-", bytes))
              .retrieve()
              .onStatus(HttpStatus::is4xxClientError, clientResponse -&gt; Mono.error(new CustomException("4xx error")))
              .onStatus(HttpStatus::is5xxServerError, clientResponse -&gt; Mono.error(new CustomException("5xx error")))
              .bodyToFlux(DataBuffer.class)
      )
      .flatMapMany(Function.identity());
  
  DataBufferUtils
          .write(fileData , fileChannel)
          .map(DataBufferUtils::release)
          .doOnError(throwable -&gt; {
              try {
                  fileChannel.force(true);
              } catch (IOException e) {
                  e.printStackTrace();
              }
          })
          .retry(3)
          .doOnComplete(() -&gt; {
              try {
                  fileChannel.force(true);
              } catch (IOException e) {
                  e.printStackTrace();
              }
          })
          .doOnError(e -&gt; !(e instanceof ChannelException), e -&gt; {
              try {
                  Files.deleteIfExists(targetPath);
              } catch (IOException exc) {
                  exc.printStackTrace();
              }
          })
          .doOnError(ChannelException.class, e -&gt; {
              try {
                  Files.deleteIfExists(targetPath);
              } catch (IOException exc) {
                  exc.printStackTrace();
              }
          })
          .doOnTerminate(() -&gt; {
              try {
                  fileChannel.close();
              } catch (IOException e) {
                  e.printStackTrace();
              }
          })
      .blockLast();
  </code></pre>
  
  <p>But apparently I am getting a full stack of errors whenever I kill my second instance of application starting with:</p>
  
  <pre><code>reactor.netty.http.client.PrematureCloseException: Connection prematurely closed DURING response
  2019-10-25T15:41:53.602+0200 [ERROR] [xxx] [N/A:N/A] [r.core.publisher.Operators] { thread=reactor-http-nio-4  } Operator called default onErrorDropped
  reactor.core.Exceptions$BubblingException: reactor.netty.http.client.PrematureCloseException: Connection prematurely closed DURING response
      at reactor.core.Exceptions.bubble(Exceptions.java:154)
      at reactor.core.publisher.Operators.onErrorDropped(Operators.java:512)
      at reactor.netty.channel.FluxReceive.onInboundError(FluxReceive.java:343)
      at reactor.netty.channel.ChannelOperations.onInboundError(ChannelOperations.java:399)
      at reactor.netty.http.client.HttpClientOperations.onInboundClose(HttpClientOperations.java:258)
      at reactor.netty.channel.ChannelOperationsHandler.channelInactive(ChannelOperationsHandler.java:121)
  </code></pre>
  
  <p>and also later in the same stack trace:</p>
  
  <pre><code>2019-10-25T15:41:53.602+0200 [WARN] [xxx] [N/A:N/A] [i.n.c.AbstractChannelHandlerContext] { thread=reactor-http-nio-4  } An exception 'reactor.core.Exceptions$BubblingException: reactor.netty.http.client.PrematureCloseException: Connection prematurely closed DURING response' [enable DEBUG level for full stacktrace] was thrown by a user handler's exceptionCaught() method while handling the following exception:
  reactor.core.Exceptions$BubblingException: reactor.netty.http.client.PrematureCloseException: Connection prematurely closed DURING response
      at reactor.core.Exceptions.bubble(Exceptions.java:154)
      at reactor.core.publisher.Operators.onErrorDropped(Operators.java:512)
      at reactor.netty.channel.FluxReceive.onInboundError(FluxReceive.java:343)
      at reactor.netty.channel.ChannelOperations.onInboundError(ChannelOperations.java:399)
      at reactor.netty.http.client.HttpClientOperations.onInboundClose(HttpClientOperations.java:258)
      at reactor.netty.channel.ChannelOperationsHandler.channelInactive(ChannelOperationsHandler.java:121)
  </code></pre>
  
  <p>The exceptions itself are not much of a problem but <strong>the point being is that my download does not resume after I boot my application back up to live.</strong></p>
  
  <p>So yeah, my question is, how could I possibly resume the downloading and how should/could I handle such exceptions as in here?</p>