Read headers from HttpResponseMessage before Content is 100% complete

佐手、 提交于 2019-12-05 01:41:04

Based on my own testing, the content won't be transferred until you start reading the content stream, and you're correct that calling Task.Result is a blocking call, but its very nature, it's a synchronisation point. But, it doesn't block to pre-buffer the entire content, it only blocks until the content starts to come from the server.

So an infinite stream won't block for an infinite amount of time. As such, trying to fetch the stream asynchronously might be deemed overkill, especially if your header processing operation is relatively short. But if you want to, you can always process the headers while the content stream is being handled on another task. Something like this would accomplish that.

static void Main(string[] args)
{
    var url = "http://somesite.com/bigdownloadfile.zip";
    var client = new HttpClient();
    var request = new HttpRequestMessage(HttpMethod.Get, url);

    var getTask = client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
    Task contentDownloadTask = null;

    var continuation = getTask.ContinueWith((t) =>
    {
        contentDownloadTask = Task.Run(() =>
        {
            var resultStream = t.Result.Content.ReadAsStreamAsync().Result;
            resultStream.CopyTo(File.Create("output.dat"));
        });

        Console.WriteLine("Got {0} headers", t.Result.Headers.Count());
        Console.WriteLine("Blocking after fetching headers, press any key to continue...");
        Console.ReadKey(true);
    });

    continuation.Wait();
    contentDownloadTask.Wait();
    Console.WriteLine("Finished downloading {0} bytes", new FileInfo("output.dat").Length);

    Console.WriteLine("Finished, press any key to exit");
    Console.ReadKey(true);
}

Note that there's no need to check if the headers portion is complete, you've explicitly specified that with the HttpCompletionOption.ResponseHeadersRead option. The SendAsync task will not continue until the headers have been retrieved.

The result using the await/async keywords it's even more readable:

var url = "http://somesite.com/bigdownloadfile.zip";

using (var httpClient = new HttpClient())
using (var httpRequest = new HttpRequestMessage(HttpMethod.Get, url ))
using(HttpResponseMessage response = await httpClient.SendAsync(httpRequest, HttpCompletionOption.ResponseHeadersRead))
using (Stream stream = await response.Content.ReadAsStreamAsync())
{
    //Access to the Stream object as it comes, buffer it or do whatever you need
}    
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!