How to Download Large Files Efficiently with Spring RestTemplate and Resume Support

This tutorial explains how to use Spring's RestTemplate to download large files without exhausting memory, covering pitfalls of default methods, implementing a custom ResponseExtractor to stream data to disk, and adding support for resumable downloads via Range headers.

Programmer DD
Programmer DD
Programmer DD
How to Download Large Files Efficiently with Spring RestTemplate and Resume Support

Overview

In this tutorial we demonstrate several techniques for downloading large files with Spring's RestTemplate.

RestTemplate

RestTemplate is a synchronous, blocking HTTP client introduced in Spring 3. It may be deprecated in future versions in favor of the non‑blocking WebClient introduced in Spring 5.

Pitfalls

Downloading a file directly into memory can cause OutOfMemoryError. Using ResourceHttpMessageConverter loads the whole response into a ByteArrayInputStream, still causing memory pressure. Configuring ResourceHttpMessageConverter#supportsReadStreaming to return InputStreamResource fails because the underlying execute method closes the response stream before the input stream can be read.

Solution

Two possible solutions are:

Write a custom HttpMessageConverter that supports File as the return type.

Use RestTemplate.execute together with a custom ResponseExtractor to stream the response directly to a file.

We focus on the second approach.

Implementation of a non‑resumable download

File file = restTemplate.execute(
    FILE_URL,
    HttpMethod.GET,
    null,
    clientHttpResponse -> {
        File ret = File.createTempFile("download", "tmp");
        StreamUtils.copy(clientHttpResponse.getBody(),
                         new FileOutputStream(ret));
        return ret;
    });
Assertions.assertNotNull(file);
Assertions.assertThat(file.length()).isEqualTo(contentLength);

Checking server support for range requests

HttpHeaders headers = restTemplate.headForHeaders(FILE_URL);
Assertions.assertThat(headers.get("Accept-Ranges")).contains("bytes");
Assertions.assertThat(headers.getContentLength()).isGreaterThan(0);

Implementation of a resumable download

File file = /* previously downloaded part */;
restTemplate.execute(
    FILE_URL,
    HttpMethod.GET,
    request -> request.getHeaders().set(
        "Range",
        String.format("bytes=%d-%d", file.length(), contentLength)),
    response -> {
        StreamUtils.copy(response.getBody(),
                         new FileOutputStream(file, true));
        return file;
    });
Assertions.assertThat(file.length()).isLessThanOrEqualTo(contentLength);

When content length is unknown

String rangeHeader = String.format("bytes=%d-", file.length());
request.getHeaders().set("Range", rangeHeader);

Conclusion

We discussed common problems when downloading large files and provided a RestTemplate‑based solution, including a method for resumable (range) downloads. The full source code is available in the linked GitHub repository.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaBackend DevelopmentspringHTTPresttemplateLarge File DownloadResume Support
Programmer DD
Written by

Programmer DD

A tinkering programmer and author of "Spring Cloud Microservices in Action"

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.