1,HttpClient
Win 8提供了System.Net.Http.HttpClient类进行常用的http网络请求,HttpClient提供了以下构造函数。
HttpClient构造函数 // 摘要:
// 初始化 System.Net.Http.HttpClient 类的新实例。
public HttpClient();
//
// 摘要:
// 用特定的处理程序初始化 System.Net.Http.HttpClient 类的新实例。
//
// 参数:
// handler:
// 用于发送请求的使用的 HTTP 处理程序堆栈。
public HttpClient(HttpMessageHandler handler);
//
// 摘要:
// 用特定的处理程序初始化 System.Net.Http.HttpClient 类的新实例。
//
// 参数:
// handler:
// System.Net.Http.HttpMessageHandler 负责处理 HTTP 响应消息。
//
// disposeHandler:
// 如果内部处理程序应由 Dispose () 处理,则为 true;如果您希望重用内部处理程序,则为 false。
public HttpClient(HttpMessageHandler handler, bool disposeHandler);
第2个构造函数常用来处理在请求前添加header(如:Cookie),响应时解析header。
下面使用HttpClient处理POST/GET提交:
#1. 让我们先来定义好key-value类型的参数,用于提交。
HttpClient Parameter public class Parameter
{
public string key { get; set; }
public string value { get; set; }
public Parameter() { }
public Parameter(string key, string value)
{
this.key = key;
this.value = value;
}
}
#2. POST/GET:
HttpClient POST/GET private static async Task<string> doRequest<T>(string url, List<Parameter> paramList, bool isPost)
{
System.Net.Http.HttpClient httpClient = null;
try
{
httpClient = new System.Net.Http.HttpClient();
httpClient.DefaultRequestHeaders.Add("user-agent", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)");
HttpResponseMessage response = null;
// POST
if (isPost)
{
MultipartFormDataContent form = getPostForm(paramList);
response = await httpClient.PostAsync(new Uri(url), form);
}
// GET
else
{
url = generateGetUrl(url, paramList);
response = await httpClient.GetAsync(new Uri(url));
}
return await response.Content.ReadAsStringAsync();
}
catch (Exception) { }
finally
{
if (httpClient != null)
{
httpClient.Dispose();
httpClient = null;
}
}
return null;
}
private static string generateGetUrl(string url, List<Parameter> paramList)
{
if(paramList == null || paramList.Count <= 0)
{
return url;
}
StringBuilder sb = new StringBuilder();
foreach (Parameter item in this.ParamList)
{
if (item == null || string.IsNullOrWhiteSpace(item.key) || string.IsNullOrWhiteSpace(item.value))
{
continue;
}
if (sb.Length > 0)
{
sb.Append("&");
}
sb.Append(string.Format("{0}={1}", item.key, System.Net.WebUtility.UrlEncode(item.value)));
}
return url + (url.IndexOf("?") == -1 ? "?" : "&") + sb.ToString();
}
private static MultipartFormDataContent getPostForm(List<Parameter> paramList)
{
MultipartFormDataContent form = new MultipartFormDataContent();
if (paramList != null)
{
foreach (var param in paramList)
{
if (!string.IsNullOrWhiteSpace(param.key))
{
form.Add(new StringContent(param.value, UTF8Encoding.UTF8), param.key);
}
}
}
return form;
}
#3. 处理Cookie,
通常情况下我们需要保持client与server之间的session,server端是通过cookie来识别一个client与另外一个client的。
我们使用上面HttpClient的第2个构造函数,通过MessageProcessingHandler和CookieContainer来每次请求前,把cookie添加到request的header中。
CookieHandler public class CookieHandler : MessageProcessingHandler
{
static CookieHandler()
{
CookieContainer = new CookieContainer();
}
public static CookieContainer CookieContainer
{
get;
set;
}
public CookieHandler() : base(new CookieHttpClientHandler())
{
}
protected override HttpRequestMessage ProcessRequest(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
return request;
}
protected override HttpResponseMessage ProcessResponse(HttpResponseMessage response, System.Threading.CancellationToken cancellationToken)
{
Uri httpsUri = new Uri("https://" + response.RequestMessage.RequestUri.Host);
var cookieCollection = CookieContainer.GetCookies(httpsUri);
foreach (Cookie cookie in cookieCollection)
{
cookie.Secure = false;
}
return response;
}
}
class CookieHttpClientHandler : HttpClientHandler
{
public CookieHttpClientHandler()
{
CookieContainer = CookieHandler.CookieContainer;
}
}
使用方式跟前面POST/GET代码唯一不同的是:在构造HttpClient对象时,传入CookieHandler:
var httpClient = new System.Net.Http.HttpClient(new CookieHandler());
2, 文件下载
#1 HttpClient提供了字节流的方式来读取文件,但我测试发现,下载是成功了,但文件经常出现缺少字节的情况。不清楚是怎么回事。
HttpClient字节处理 //
// 摘要:
// 将 GET 请求发送到指定 URI 并在异步操作中以字节数组的形式返回响应正文。
//
// 参数:
// requestUri:
// 请求发送到的 URI。
//
// 返回结果:
// 返回 System.Threading.Tasks.Task<TResult>。 表示异步操作的任务对象。
//
// 异常:
// System.ArgumentNullException:
// requestUri 为 null。
public Task<byte[]> GetByteArrayAsync(string requestUri);
//
// 摘要:
// 将 GET 请求发送到指定 URI 并在异步操作中以字节数组的形式返回响应正文。
//
// 参数:
// requestUri:
// 请求发送到的 URI。
//
// 返回结果:
// 返回 System.Threading.Tasks.Task<TResult>。 表示异步操作的任务对象。
//
// 异常:
// System.ArgumentNullException:
// requestUri 为 null。
public Task<byte[]> GetByteArrayAsync(Uri requestUri);
//
// 摘要:
// 将 GET 请求发送到指定 URI 并在异步操作中以流的形式返回响应正文。
//
// 参数:
// requestUri:
// 请求发送到的 URI。
//
// 返回结果:
// 返回 System.Threading.Tasks.Task<TResult>。 表示异步操作的任务对象。
//
// 异常:
// System.ArgumentNullException:
// requestUri 为 null。
public Task<System.IO.Stream> GetStreamAsync(string requestUri);
//
// 摘要:
// 将 GET 请求发送到指定 URI 并在异步操作中以流的形式返回响应正文。
//
// 参数:
// requestUri:
// 请求发送到的 URI。
//
// 返回结果:
// 返回 System.Threading.Tasks.Task<TResult>。 表示异步操作的任务对象。
//
// 异常:
// System.ArgumentNullException:
// requestUri 为 null。
public Task<System.IO.Stream> GetStreamAsync(Uri requestUri);
#2. BackgroundDownloader
Win 8提供了BackgroundDownloader可以用于在后台下载文件,它也可以调用setRequestHeader向请求中添加header信息(与上面的CookieHandler结合使用,可以处理那些需要登陆才能下载文件的情况),下面演示了普通的文件下载:
BackgroundDownloader文件下载 public async static Task<IAsyncOperation<StorageFile>> DownloadAsync(string url)
{
string fileName = url.Substring(url.LastIndexOf("/") + 1).Trim();
var option = Windows.Storage.CreationCollisionOption.ReplaceExisting;
StorageFile destinationFile = await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFileAsync(fileName, option);
BackgroundDownloader downloader = new BackgroundDownloader();
DownloadOperation download = downloader.CreateDownload(new Uri(url), destinationFile);
await download.StartAsync().AsTask();
ResponseInformation response = download.GetResponseInformation();
if(response.StatusCode == 200)
{
DownloadHelper.addDownloadFileSuccess(fileName);
return DownloadHelper.getDownloadFileAsync(fileName);
}
return null;
}