All 15 Java Networking & HTTP Client questions
More in Java Networking & HTTP Client
Advertisement
Java › Java Networking & HTTP Client

How would you implement a custom BodySubscriber or BodyHandler to stream a very large HTTP response body incrementally, rather than buffering the entire response into memory at once?

Advanced

Answer

HttpResponse.BodyHandlers provides several built-in options beyond the common ofString()/ofByteArray() (which fully buffer the response body in memory before returning), including ofInputStream() (returns a standard InputStream you can read incrementally) and ofLines() (returns a Stream<String> of lines, lazily evaluated) -- for genuinely custom streaming processing needs, implementing your own BodySubscriber<T> gives full low-level control over how response body bytes are consumed as they arrive over the network, letting you process a very large response (like a multi-gigabyte file download) incrementally without ever holding the complete body in memory simultaneously.
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://example.com/large-file.zip"))
    .build();

// Stream the response body directly to a file, without buffering it fully in memory
HttpResponse<Path> response = client.send(request,
    HttpResponse.BodyHandlers.ofFile(Path.of("downloaded-file.zip")));

// Or process line-by-line for a large text response
HttpResponse<Stream<String>> lineResponse = client.send(request, HttpResponse.BodyHandlers.ofLines());
lineResponse.body().forEach(line -> processLine(line));
Real-world example A data-synchronization service downloading multi-gigabyte export files from a partner API uses HttpResponse.BodyHandlers.ofFile() to stream the response directly to disk incrementally, avoiding the out-of-memory risk that buffering the entire multi-gigabyte response into a byte array or String first would create.

Common follow-ups: What's the performance and memory trade-off of ofInputStream() versus a fully custom BodySubscriber implementation?;How would you implement progress reporting (bytes downloaded so far) for a large streaming download using a custom BodySubscriber?