.Net 4.5中的HttpClient使用方法
2016-05-07 15:07
591 查看
原文http://www.cnblogs.com/TianFang/archive/2012/03/10/2389480.html
.Net 4.5中增加了一个新的System.Net.Http.HttpClient名字空间(在 System.Net.Http.dll 中),用于发送 HTTP 请求和接收 HTTP 响应。
基本操作
和以前的HttpWebRequest相比,HttpClient更加简洁,下面就是一个下载www.windows.com页面的示例:
string uri = "http://www.windows.com/";
HttpClient client = new HttpClient();
string body = await client.GetStringAsync(uri);
它支持编码识别和对压缩的http流解压,省去了我们的不少代码。除GetStringAsync()之外,还有GetByteArrayAsync()、GetStreamAsync()、PostAsync
()、DeleteAsync()等函数,非常好用。
HttpClient.GetStringAsync()是一个简化的函数,用这个函数的时候,我们看不到HttpResponse的相关信息,如果需要看到Http响应的信息,可以用如下标准方式:
HttpResponseMessage response = await client.GetAsync(uri);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
自定义HttpHeader
前面的示例非常简单,但有时我们需要在发送Get请求时在HttpHeader中加入一些额外的信息,常见的的有Refer、Cookie及UserAgent等。这个时候我们就要用到HttpClientHandler了,具体方法如下:
首先自定义一个HttpClienHanlder类,重载SendAsync方法。
string uri = "http://www.windows.com/";
HttpClient client = new HttpClient();
class MyHttpClienHanlder:HttpClientHandler
{
protected override Task<HttpResponseMessage>
SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
request.Headers.Referrer = new Uri("http://www.google.com/");
request.Headers.Add("UserAgent", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727)");
return base.SendAsync(request, cancellationToken);
}
}
在HttpClient构造函数中加入自定义的HttpClienHanlder类。
string uri = "http://www.windows.com/";
HttpClient client = new HttpClient(new MyHttpClienHanlder());
string body = await client.GetStringAsync(uri);
可见,HttpClienHanlder其实就是是一个常见的代理模式的设计,它在HttpClient.GetStringAsync()中加了一层封装,拦截了HttpClient的输入和输出,从而实现一些自定义的操作。
常见问题
HttpClient虽然非常简单易用,但并不意味着它任何时候都能照着我们期望的方式工作,常见问题(我这两天试用过程中遇到的)如下:
中文乱码
HttpClient.GetStringAsync()本身支持编码识别,但如果HttpResponse的HttpHeader中不含CharSet信息时,便采用默认编码方式进行字符串解码,它的默认编码方式是无法解析中文的,此时便会出现中文乱码。
一种常见的做法是:如果HttpHeader中不含CharSet信息时,采用GBK方式来解码。要实现这个功能的话,还是需要用到前面提到的HttpClientHandler。
class MyHttpClienHanlder:HttpClientHandler
{
protected async override Task<HttpResponseMessage>
SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var rsponse = await base.SendAsync(request, cancellationToken);
var contentType = rsponse.Content.Headers.ContentType;
if (string.IsNullOrEmpty(contentType.CharSet))
{
contentType.CharSet = "GBK";
}
return rsponse;
}
}
当然,这么做仍然不是很完善,有的时候如果要更精确的话还需要从Html页面中获取charset信息,甚至通过相应的库函数进行编码猜测。这儿我写了一个稍微完善的版本:
响应内容过长导致HttpRequestException
HttpClient有一个属性MaxResponseContentBufferSize,它表示的是读取响应内容时最大字节数缓冲区。它的默认值是64k,当页面内容很多,超过64k的时候,就会抛出一个HttpRequestException,导致Get失败。
这个属性必须是个正整数,也就是说,它是不支持自适应的,这个非常令人费解,不知道MS为什么非要自己估算页面大小,在Get操作前支持为合适的值,这个是个不够好用的地方。
我查了一下MSDN,目前对这个属性的说明比较少,不知道更改这个值的大小会影响什么地方。即使把他设置成int.Max貌似也不会有过多的内存占用。不过为了安全起见,还是把它设置在一个合理的范围吧,像我一般就把它设置为1m。(PS: 在最新的.Net 4.5 RC中,这个值已经更新成了int.MaxValue,希望RTM版不要恢复成64k,确实不够用)
HttpClient client = new HttpClient()
{ MaxResponseContentBufferSize = 1024 * 1024 };
最后提一个不是问题的问题:HttpClient全部都是异步方法,没有同步方法,如果要在同步函数中使用,必须通过Task.Wait()来等待任务完成,稍稍有些不便。
.Net 4.5中增加了一个新的System.Net.Http.HttpClient名字空间(在 System.Net.Http.dll 中),用于发送 HTTP 请求和接收 HTTP 响应。
基本操作
和以前的HttpWebRequest相比,HttpClient更加简洁,下面就是一个下载www.windows.com页面的示例:
string uri = "http://www.windows.com/";
HttpClient client = new HttpClient();
string body = await client.GetStringAsync(uri);
它支持编码识别和对压缩的http流解压,省去了我们的不少代码。除GetStringAsync()之外,还有GetByteArrayAsync()、GetStreamAsync()、PostAsync
()、DeleteAsync()等函数,非常好用。
HttpClient.GetStringAsync()是一个简化的函数,用这个函数的时候,我们看不到HttpResponse的相关信息,如果需要看到Http响应的信息,可以用如下标准方式:
HttpResponseMessage response = await client.GetAsync(uri);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
自定义HttpHeader
前面的示例非常简单,但有时我们需要在发送Get请求时在HttpHeader中加入一些额外的信息,常见的的有Refer、Cookie及UserAgent等。这个时候我们就要用到HttpClientHandler了,具体方法如下:
首先自定义一个HttpClienHanlder类,重载SendAsync方法。
string uri = "http://www.windows.com/";
HttpClient client = new HttpClient();
class MyHttpClienHanlder:HttpClientHandler
{
protected override Task<HttpResponseMessage>
SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
request.Headers.Referrer = new Uri("http://www.google.com/");
request.Headers.Add("UserAgent", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727)");
return base.SendAsync(request, cancellationToken);
}
}
在HttpClient构造函数中加入自定义的HttpClienHanlder类。
string uri = "http://www.windows.com/";
HttpClient client = new HttpClient(new MyHttpClienHanlder());
string body = await client.GetStringAsync(uri);
可见,HttpClienHanlder其实就是是一个常见的代理模式的设计,它在HttpClient.GetStringAsync()中加了一层封装,拦截了HttpClient的输入和输出,从而实现一些自定义的操作。
常见问题
HttpClient虽然非常简单易用,但并不意味着它任何时候都能照着我们期望的方式工作,常见问题(我这两天试用过程中遇到的)如下:
中文乱码
HttpClient.GetStringAsync()本身支持编码识别,但如果HttpResponse的HttpHeader中不含CharSet信息时,便采用默认编码方式进行字符串解码,它的默认编码方式是无法解析中文的,此时便会出现中文乱码。
一种常见的做法是:如果HttpHeader中不含CharSet信息时,采用GBK方式来解码。要实现这个功能的话,还是需要用到前面提到的HttpClientHandler。
class MyHttpClienHanlder:HttpClientHandler
{
protected async override Task<HttpResponseMessage>
SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var rsponse = await base.SendAsync(request, cancellationToken);
var contentType = rsponse.Content.Headers.ContentType;
if (string.IsNullOrEmpty(contentType.CharSet))
{
contentType.CharSet = "GBK";
}
return rsponse;
}
}
当然,这么做仍然不是很完善,有的时候如果要更精确的话还需要从Html页面中获取charset信息,甚至通过相应的库函数进行编码猜测。这儿我写了一个稍微完善的版本:
class HtmlTextHandler : HttpClientHandler { protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { var response = await base.SendAsync(request, cancellationToken); var contentType = response.Content.Headers.ContentType; contentType.CharSet = await getCharSetAsync(response.Content); return response; } private async Task<string> getCharSetAsync(HttpContent httpContent) { var charset = httpContent.Headers.ContentType.CharSet; if (!string.IsNullOrEmpty(charset)) return charset; var content = await httpContent.ReadAsStringAsync(); var match = Regex.Match(content, @"charset=(?<charset>.+?)""", RegexOptions.IgnoreCase); if (!match.Success) return charset; return match.Groups["charset"].Value; } }
响应内容过长导致HttpRequestException
HttpClient有一个属性MaxResponseContentBufferSize,它表示的是读取响应内容时最大字节数缓冲区。它的默认值是64k,当页面内容很多,超过64k的时候,就会抛出一个HttpRequestException,导致Get失败。
这个属性必须是个正整数,也就是说,它是不支持自适应的,这个非常令人费解,不知道MS为什么非要自己估算页面大小,在Get操作前支持为合适的值,这个是个不够好用的地方。
我查了一下MSDN,目前对这个属性的说明比较少,不知道更改这个值的大小会影响什么地方。即使把他设置成int.Max貌似也不会有过多的内存占用。不过为了安全起见,还是把它设置在一个合理的范围吧,像我一般就把它设置为1m。(PS: 在最新的.Net 4.5 RC中,这个值已经更新成了int.MaxValue,希望RTM版不要恢复成64k,确实不够用)
HttpClient client = new HttpClient()
{ MaxResponseContentBufferSize = 1024 * 1024 };
最后提一个不是问题的问题:HttpClient全部都是异步方法,没有同步方法,如果要在同步函数中使用,必须通过Task.Wait()来等待任务完成,稍稍有些不便。
相关文章推荐
- XMLHttpRequest发送JSON请求
- XMLHttpRequest发送XML请求
- XMLHttpRequest发送POST请求
- XMLHttpRequset发送GET请求
- iOS 应用如何完全支持 IPv6-ONLY 网络?
- 关于怎样搭建企业网盘及WEB服务器
- Ubuntu网络配置
- XMLHttpRequest的属性
- NetBSD 网络配置
- 大端模式、小端模式和网络字节顺序【转】
- XMLHttpRequest的方法
- linux下简单socket网络编程
- 网络仿真软件eNSP
- TCP/IP、UDP、HTTP、Socket详解
- 5-36 社交网络图中结点的“重要性”计算 (30分)
- Ubuntu搭建Openstack平台(kilo)(六.实例化网络,创建实例)
- 路由器有线无法上网,此计算机上缺少一个或多个网络协议——解决方法
- [javaSE] 网络编程(TCP通信)
- linux网络编程实践
- window7下VMware网络设置-固定ip