httpclient

在此讲一下httpclient类的使用,在之前《网络数据请求request》中讲过WebClient和HttpWebRequest ,在此讲一下httpclient,同时对《网络数据请求request》中的一些问题进行优化。

httpclient需要.net4.5以上,在System.Net.Http;命名空间下。httpclient通过关键字await实现异步操作,方便简洁而且效率高,缺点是需要较高的.net版本。对于get和post方法分别采用await以及task的continewith进行异步操作;

1)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)post

post对应于不同的contentType对应四种提交数据的方法,具体可参见《网络数据请求request》,在此不在赘述,不管是何种类型的请求,httpclient的请求主体可以通过表单(FormUrlEncodedContent或者MultipartFormDataContent等继承自httpcontent类)进行进行提交,而不必自己构造请求主体。

(一)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));                
               });
        }

 

(一)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();
        }
    }
}

 

 

PS:1)主程序中除其他参数外,提交的文件只需要在postParameter添加对应的提交参数与文件路径即可

      2)《网络数据请求request》中为了体现text文件与image文件的不同,采取不同的获取文件数据的方式(image通过Bitmap 类获取数据),本例中都采用一般文件获取文件信息

      3)代码中api_key、api_secret分别为face++的key和secret,涉及到账号问题已经抹去,代码测试可以去申请一个账号,很容易。

      4)代码亲测有效,但在异常处理方面未做周全考虑,使用者可以自己根据需求在做相关处理

 

posted @ 2017-11-03 13:58  81192  阅读(370)  评论(0编辑  收藏  举报