title: "C11. Use the Progress Callback" order: 11
To display download or upload progress, pass a DownloadProgress or UploadProgress callback. Both take two arguments: (current, total).
httplib::Client cli("http://localhost:8080");
auto res = cli.Get("/large-file",
[](size_t current, size_t total) {
auto percent = (total > 0) ? (current * 100 / total) : 0;
std::cout << "\rDownloading: " << percent << "% ("
<< current << "/" << total << ")" << std::flush;
return true; // return false to abort
});
std::cout << std::endl;
The callback fires each time data arrives. total comes from the Content-Length header. For a response without one (chunked transfer, for example), the progress callback is not called at all.
Uploads work the same way. Pass an UploadProgress as the last argument to Post() or Put().
httplib::Client cli("http://localhost:8080");
std::string body = load_large_body();
auto res = cli.Post("/upload", body, "application/octet-stream",
[](size_t current, size_t total) {
auto percent = current * 100 / total;
std::cout << "\rUploading: " << percent << "%" << std::flush;
return true;
});
std::cout << std::endl;
Return false from the callback to abort the transfer. This is how you wire up a "Cancel" button in a UI — flip a flag, and the next progress tick stops the transfer.
std::atomic<bool> cancelled{false};
auto res = cli.Get("/large-file",
[&](size_t current, size_t total) {
return !cancelled.load();
});
Note: A response without Content-Length never calls the progress callback, so it cannot be cancelled this way. Return
falsefrom aContentReceiverinstead.Note:
ContentReceiverand the progress callback can be used together. When you want to stream to a file and show progress at the same time, pass both.For a concrete example of saving to a file, see C01. Get the response body / save to a file.