Search code examples
c#.netdotnet-httpclient.net-4.6.2

HttpClient SendAsync and HttpContent CopyToAsync


I'm using HttpClient to download a file. I wanted to know at what point the resource is actually downloaded over the network (Wanted to calculate the download rate)? After creating the client, I use SendAsync and immediately access the HttpContent from the response and use the content's CopyToAsync method to copy to a file. Is the file downloaded when the SendAsync call is made or when I call CopyToAsync? This is for .Net 4.6.2


Solution

  • By default, SendAsync uses the ResponseContentRead HTTP completion option, which means the response is entirely cached in memory before the returned task completes, and thus, reading the response's contents simply copies from the cached memory data. This has the benefit of allowing you to read multiple times from the response, at the cost of increasing memory usage.

    The side effect of this is that by the time you start reading from the stream, the file is already fully downloaded, which means whatever calculations you do for download rate will be meaningless.

    If you want to copy the file as it is being downloaded, pass ResponseHeadersRead to SendAsync. This will make it so the task returned by SendAsync completes as soon as the headers are read:

    using var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
    // here, response only contains the response headers
    response.EnsureSuccessStatusCode();
    using var stream = await response.Content.ReadAsStreamAsync();
    // start reading from stream
    await stream.CopyToAsync(file); // download and write at the same time
    

    If you do that, however, you have to dispose the response when you're done reading (ideally with a using statement, as shown above) so that the connection is closed as soon as possible, as using ResponseHeadersRead will make the response hold on to OS resources until disposed (or finalised), unlike with ResponseContentRead, with which the client can release those as soon as the download is finished. In practice this is not really a problem because you should always dispose your disposable objects before they go out of scope, but it's still something to keep in mind.