在UWP下,低级HttpWebRequest
类及其同类已被弃用,the official recommendation将使用System.Net.Http.HttpClient
但是,HttpClient
实现中似乎存在明显的疏忽或错误:API似乎没有提供对远程URI发出请求的方法,该远程URI不会自动下载整个远程资源(在GET
请求的情况下)允许对响应流进行惰性评估。
The documentation for the HttpClient.GetAsync()
method说:
此操作不会阻止。在读取完整个响应(包括内容)后,返回的任务对象将完成。
在认为完成请求之前,会提前说明将下载整个远程资源。如果指定HttpCompletionOption
,理论上允许解决此问题的HttpCompletionOption.ResponseHeadersRead
参数,如下所示:
一旦响应可用并且读取标题,操作就应该完成。内容尚未阅读。
但是,无论指定了哪个HttpCompletionOption
,在所有情况下,HttpClient.GetAsync()
似乎都会分配响应的完整ContentLength
字节(在内存中!一次性!没有任何限制)检查!)在这个过程中。当然,这有点疯狂,是一个真正的问题。
在我的特定情况下,我只想从不支持http范围标头的服务器读取数千兆字节远程资源的前几个kb。这通常是一种“无汗”的操作:只需创建Web请求,从响应流中读取,直到您满意为止,然后关闭响应并以愉快的方式进行。
这似乎不是默认HttpClient
API的选项。是否有一个简单的解决方法,不涉及使用原始套接字制作我自己的HTTP请求?
答案 0 :(得分:1)
在所有情况下,HttpClient.GetAsync()似乎分配响应的完整ContentLength字节(在内存中!一次性!没有任何限制检查!)
HttpCompletionOption.ResponseHeadersRead
选项不适用。
就像使用旧的sweet HttpWebRequest
类一样,您可以打开响应流并读取几个字节,然后丢弃响应。这是an example。
这是我的实验:(我使用的是Windows.Web.Http.HttpClient,但System.Net.Http.HttpClient提供了类似的API)
private HttpClient httpClient = new HttpClient();
private CancellationTokenSource cts = new CancellationTokenSource();
private async void MainPage_Loaded(object sender, RoutedEventArgs e)
{
Uri resourceAddress = new Uri("http://somewhere/gigabyte.zip");
try
{
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, resourceAddress);
// Do not buffer the response.
HttpResponseMessage response = await httpClient.SendRequestAsync(
request,
HttpCompletionOption.ResponseHeadersRead).AsTask(cts.Token);
using (Stream responseStream = (await response.Content.ReadAsInputStreamAsync()).AsStreamForRead())
{
int read = 0;
byte[] responseBytes = new byte[1000];
do
{
read = await responseStream.ReadAsync(responseBytes, 0, responseBytes.Length);
break;
} while (read != 0);
}
}
catch (TaskCanceledException)
{
}
catch (Exception ex)
{
}
finally
{
}
}