我使用HttpClient下载文件。我想知道资源实际上是在什么时候通过网络下载的(想要计算下载率)?在创建客户机之后,我使用SendAsync并立即从响应访问HttpContent,并使用内容的CopyToAsync方法将其复制到文件中。文件下载时,SendAsync调用或当我调用CopyToAsync?这是针对。net 4.6.2
的默认情况下,SendAsync
使用ResponseContentRead
HTTP完成选项,这意味着在返回的任务完成之前,响应完全缓存在内存中,因此,读取响应的内容只是从缓存的内存数据中复制。这样做的好处是允许您从响应中读取多次,但代价是增加内存使用。
这样做的副作用是,当你开始从流中读取时,文件已经完全下载了,这意味着你对下载速率所做的任何计算都将毫无意义。
如果您想在下载时复制文件,将ResponseHeadersRead
传递给SendAsync
。这将使SendAsync
返回的任务在读取头文件后立即完成:
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
如果您这样做,但是,当您完成读取时,必须处置响应(理想情况下使用using
语句,如上所示),以便尽快关闭连接,因为使用ResponseHeadersRead
将使响应保持操作系统资源直到处置(或完成),不像使用ResponseContentRead
,客户端可以在下载完成后立即释放这些资源。在实践中,这并不是一个真正的问题,因为您应该总是在一次性对象超出作用域之前处理它们,但这仍然是要记住的事情。