文章目录
前言
在此讲一下httpclient类的使用,在之前《网络数据请求request》中讲过WebClient和HttpWebRequest ,在此讲一下httpclient,同时对《网络数据请求request》中的一些问题进行优化。
httpclient需要.net4.5以上,在System.Net.Http;命名空间下。httpclient通过关键字await实现异步操作,方便简洁而且效率高,缺点是需要较高的.net版本。对于get和post方法分别采用await以及task的continewith进行异步操作;
1.0 get
/// <summary>
/// await 异步请求
/// get
/// </summary>
static async void HttpClientGetAsync()
{
HttpClient httpClient = new HttpClient();
HttpResponseMessage response = await httpClient.GetAsync("http://www.sojson.com/open/api/weather/json.shtml?city=闵行区");
response.EnsureSuccessStatusCode();
string result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
/// <summary>
/// task 请求
/// get
/// </summary>
static void HttpClientGet()
{
HttpClient httpClient = new HttpClient();
httpClient.GetAsync("http://www.sojson.com/open/api/weather/json.shtml?city=闵行区").ContinueWith(
(getTask) =>
{
HttpResponseMessage response = getTask.Result;
response.EnsureSuccessStatusCode();
response.Content.ReadAsStringAsync().ContinueWith(
(readTask) => Console.WriteLine(readTask.Result));
});
}
1.1 post
post对应于不同的contentType对应四种提交数据的方法,具体可参见《网络数据请求request》,在此不在赘述,不管是何种类型的请求,httpclient的请求主体可以通过表单(FormUrlEncodedContent或者MultipartFormDataContent等继承自httpcontent类)进行进行提交,而不必自己构造请求主体。
1.1.1 contentType=application/x-www-form-urlencoded
/// <summary>
/// post await
///
/// </summary>
static async void HttpClientPostAsync()
{
HttpClient httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Add("Method", "Post");
httpClient.DefaultRequestHeaders.Add("KeepAlive", "false");// HTTP KeepAlive设为false,防止HTTP连接保持
HttpContent postContent = new FormUrlEncodedContent(new Dictionary<string, string>()
{
{"api_key", "3333333333333333333333333333333"},
{"api_secret", "33333333333333333333333333333333333333"},
{"image_url","https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1508759666809&di=b3748df04c5e54d18fe52ee413f72f37&imgtype=0&src=http%3A%2F%2Fimgsrc.baidu.com%2Fimgad%2Fpic%2Fitem%2F562c11dfa9ec8a1389c45414fd03918fa1ecc06c.jpg" }
});
HttpResponseMessage response = await httpClient.PostAsync("https://api-cn.faceplusplus.com/facepp/v3/detect", postContent);
response.EnsureSuccessStatusCode();
string result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
/// <summary>
/// post task请求
/// </summary>
static void HttpClientPost()
{
HttpClient httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Add("Method", "Post");
httpClient.DefaultRequestHeaders.Add("KeepAlive", "false");// HTTP KeepAlive设为false,防止HTTP连接保持
// post form
HttpContent postContent = new FormUrlEncodedContent(new Dictionary<string, string>()
{
{"api_key", "3333333333333333333333"},
{"api_secret", "333333333333333333333333333333"},
{"image_url","https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1508759666809&di=b3748df04c5e54d18fe52ee413f72f37&imgtype=0&src=http%3A%2F%2Fimgsrc.baidu.com%2Fimgad%2Fpic%2Fitem%2F562c11dfa9ec8a1389c45414fd03918fa1ecc06c.jpg" }
});
httpClient
.PostAsync("https://api-cn.faceplusplus.com/facepp/v3/detect", postContent)
.ContinueWith(
(postTask) =>
{
HttpResponseMessage response = postTask.Result;
response.EnsureSuccessStatusCode();
response.Content.ReadAsStringAsync().ContinueWith(
(readTask) => Console.WriteLine(readTask.Result));
});
}
1.1.2 multipart/form-data
采用此种方式是为了提交文件,请求主体通过表单类进行提交,不必自己构造主体,节省很大工作量。提交数据主体跟《网络数据请求request》中的一样,不过提交数据表单头如Content-disposition: form-data; name=“key2” 需要在提交内容的header中添加,代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Http;
using System.IO;
using System.Net.Http.Headers;
namespace HttpClientPostFile
{
class RequestHttpClient
{
public class FilePost //image
{
public string fullPath;
public string imageName;
public string contentType = "application/octet-stream";
public FilePost(string path)
{
fullPath = path;
imageName = Path.GetFileName(path);
}
}
private static HttpContent GetMultipartForm(Dictionary<string,object> postForm)
{
string boundary = string.Format("--{0}", Guid.NewGuid());
MultipartFormDataContent httpContent = new MultipartFormDataContent(boundary);
foreach(KeyValuePair<string,object> pair in postForm)
{
if(pair.Value is FilePost)
{
FilePost file = (FilePost)pair.Value;
byte[] b = File.ReadAllBytes(file.fullPath);
ByteArrayContent byteArrContent = new ByteArrayContent(File.ReadAllBytes(file.fullPath));
byteArrContent.Headers.Add("Content-Type", "application/octet-stream");
byteArrContent.Headers.Add("Content-Disposition",string.Format("form-data; name={0}; filename={1}",pair.Key,file.imageName));
httpContent.Add(byteArrContent);
}
else
{
string value = (string)pair.Value;
StringContent stringContent = new StringContent(value);
stringContent.Headers.Add("Content-Disposition",string.Format("form-data; name={0}",pair.Key));
httpContent.Add(stringContent);
}
}
return httpContent;
}
private static async void HttpClientPostFileAsync(HttpContent httpContent,string url)
{
string result = "";
HttpClient httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Add("Method", "Post");
httpClient.DefaultRequestHeaders.Add("KeepAlive", "false");// HTTP KeepAlive设为false,防止HTTP连接保持
try
{
HttpResponseMessage response = await httpClient.PostAsync(url, httpContent);
response.EnsureSuccessStatusCode();
result = await response.Content.ReadAsStringAsync();
}
catch(HttpRequestException ex)
{
result = ex.Message;
}
Console.WriteLine(result);
}
public static void HttpRequestByPostfileAsync(Dictionary<string,object> postForm,string url)
{
HttpClientPostFileAsync(GetMultipartForm(postForm), url);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace HttpClientPostFile
{
class Program
{
static void Main(string[] args)
{
string path = @"D:\test\image\1.jpg";
string url = "https://api-cn.faceplusplus.com/facepp/v3/detect";
RequestHttpClient.FilePost filePost = new RequestHttpClient.FilePost(path);
Dictionary<string, object> postParameter = new Dictionary<string, object>();
postParameter.Add("api_key", "3333333333333333");
postParameter.Add("api_secret", "3333333333333333333333333");
postParameter.Add("image_file", filePost);
//postParameter.Add("image_url", "http://imgtu.5011.net/uploads/content/20170328/7150651490664042.jpg");
RequestHttpClient.HttpRequestByPostfileAsync(postParameter, url);
Console.ReadKey();
}
}
}
1.2 其他
1)主程序中除其他参数外,提交的文件只需要在postParameter添加对应的提交参数与文件路径即可
2)《网络数据请求request》中为了体现text文件与image文件的不同,采取不同的获取文件数据的方式(image通过Bitmap 类获取数据),本例中都采用一般文件获取文件信息
3)代码中api_key、api_secret分别为face++的key和secret,涉及到账号问题已经抹去,代码测试可以去申请一个账号,很容易。
4)代码亲测有效,但在异常处理方面未做周全考虑,使用者可以自己根据需求在做相关处理