Progress Tracking¶
You can track download & upload progress using Methanol's ProgressTracker
.
Setup¶
A ProgressTracker
controls the rate at which progress events are propagated using two thresholds:
bytes transferred & time passed, both calculated since the last event.
// Receive a progress event at least each 50 kBs of data
var tracker = ProgressTracker.newBuilder()
.bytesTransferredThreshold(50 * 1024)
.build();
// Receive a progress event at least each half a second
var tracker = ProgressTracker.newBuilder()
.timePassedThreshold(Duration.ofSeconds(1).dividedBy(2))
.build();
Tip
You can use the builder to set an Executor
that's used for dispatching progress events to
your listener. That's useful in case your listener does something like GUI updates.
You'd want it to be invoked in the GUI thread rather than an arbitrary HTTP client thread.
```java hl_lines="3"
var tracker = ProgressTracker.newBuilder()
.bytesTransferredThreshold(50 * 1024)
.executor(javafx.application.Platform::runLater)
.build();
```
Usage¶
You track download progress by attaching a Listener
to a response's BodyHandler
. Similarly, upload
progress is tracked by registering a Listener
with a request's BodyPublisher
.
final Methanol client = Methanol.create();
final ProgressTracker tracker = ProgressTracker.newBuilder()
.bytesTransferredThreshold(60 * 1024) // 60 kB
.build();
HttpResponse<Path> downloadVeryInterestingVideo() throws IOException, InterruptedException {
var request = MutableRequest.GET("https://i.imgur.com/NYvl8Sy.mp4");
var downloadingBodyHandler = BodyHandlers.ofFile(
Path.of("interesting-video.mp4"), CREATE, WRITE);
var trackingBodyHandler = tracker.tracking(downloadingBodyHandler, this::onProgress);
return client.send(request, trackingBodyHandler);
}
void onProgress(Progress progress) {
if (progress.determinate()) { // Overall progress can be measured
var percent = 100 * progress.value();
System.out.printf(
"Downloaded %d from %d bytes (%.2f%%)%n",
progress.totalBytesTransferred(), progress.contentLength(), percent);
} else {
System.out.println("Downloaded " + progress.totalBytesTransferred());
}
if (progress.done()) {
System.out.println("Done!");
}
}
final Methanol client = Methanol.create();
final ProgressTracker tracker = ProgressTracker.newBuilder()
.bytesTransferredThreshold(60 * 1024) // 60 kB
.build();
<T> HttpResponse<T> upload(Path file, BodyHandler<T> bodyHandler)
throws IOException, InterruptedException {
var trackingRequestBody = tracker.tracking(BodyPublishers.ofFile(file), this::onProgress);
var request = MutableRequest.POST("https://httpbin.org/post", trackingRequestBody);
return client.send(request, bodyHandler);
}
void onProgress(Progress progress) {
if (progress.determinate()) { // Overall progress can be measured
var percent = 100 * progress.value();
System.out.printf(
"Uploaded %d from %d bytes (%.2f%%)%n",
progress.totalBytesTransferred(), progress.contentLength(), percent);
} else {
System.out.println("Uploaded " + progress.totalBytesTransferred());
}
if (progress.done()) {
System.out.println("Done!");
}
}