Hello 👋👋, so in this post, I will be writing about what makes a file download resumable in browsers or download managers.
So how it all started was I just wanted to build a simple download manager app using WPF(Windows Presentation Foundation) to understand how to handle states and the working principles of WPF.
So I asked questions like:-
- Do download managers or browsers use a long running socket connection to resume or pause downloads?
- How are these clients able to resume from where they stopped without re-downloading previous data chunks?
In my quest to discover how these occur by making some research online, I got to learn about the HTTP Range request header.
The Range header is a request header that allows the HTTP client to request for a specific partition or chunk of data from a file or resource.
So the usual flow of using the range header is :
- Make a HEAD request : The response from the HEAD request to the resource you want to download would contain some headers which would be used to check if the resource you want to download allows the use of the Range header to request for chunks. A simple HEAD request could be made using the code below:
//client code
var client = new HttpClient();
HttpResponseMessage response = await client.GetAsync("file-url", HttpCompletionOption.ResponseHeadersRead);
- If the Accept-Ranges header received after making the HEAD request has a value other than “none”, that means the resource supports using the Range header to request for chunks of it.
- If it supports the Range header, the response also comes with the Content-Length header and a value that represents the size of the resource or file.
- The Content-Length header can be used to know the limit of what could be requested for from the client (browser or download manager).
- So with this in place if you decide to pause your download for any reason you can also resume the process from where it stopped without consuming data redownloading the already downloaded chunks of data.
- Requesting for a range can be achieved by checking the size of the already downloaded data and subtracting it from the content length gotten during the initial HEAD request.
- For instance, if the Content-Length’s header value is 2500 bytes and 500 bytes of the file is downloaded before pausing the download. To request for the remaining chunks you can attach the Range header using the example below
curl http://examplefile.com.jpeg -i -H "Range: bytes=501-2500"
You could easily enable Range processing in your DotNet minimal API by using the following code below:
//server code
// accessing the vid route
app.MapGet("/vid", () =>
{
return Results.File(
Path.Combine(builder.Environment.ContentRootPath, "[fileLocation]"),
"[contentType]",
enableRangeProcessing: true);
});
You can check out my download manager desktop application code here. ( The ranges header made it possible to function)
You can also read more about HTTP range requests here.
Thanks for reading.