從新想象 Windows 8.1 Store Apps (88) - 通訊的新特性: 新的 HttpClient

[源碼下載]


html

從新想象 Windows 8.1 Store Apps (88) - 通訊的新特性: 新的 HttpClient



做者:webabcd


介紹
從新想象 Windows 8.1 Store Apps 之通訊的新特性html5

  • 新的 HttpClient
  • http get string
  • http get stream
  • http post string
  • http post stream



示例
HTTP 服務端
WebServer/HttpDemo.aspx.csios

/*
 * 用於響應 http 請求
 */

using System;
using System.IO;
using System.Threading;
using System.Web;

namespace WebServer
{
    public partial class HttpDemo : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            // 停 3 秒,以方便測試 http 請求的取消
            Thread.Sleep(3000);

            var action = Request.QueryString["action"];

            switch (action)
            {
                case "getString": // 響應 http get string 
                    Response.Write("hello webabcd: " + DateTime.Now.ToString("hh:mm:ss"));
                    break;
                case "getStream": // 響應 http get stream 
                    Response.Write("hello webabcd hello webabcd hello webabcd hello webabcd hello webabcd hello webabcd hello webabcd hello webabcd hello webabcd hello webabcd hello webabcd hello webabcd");
                    break;
                case "postString": // 響應 http post string 
                    Response.Write(string.Format("param1:{0}, param2:{1}, referrer:{2}", Request.Form["param1"], Request.Form["param2"], Request.UrlReferrer));
                    break;
                case "postStream": // 響應 http post stream 
                    using (StreamReader reader = new StreamReader(Request.InputStream))
                    {
                        if (Request.InputStream.Length > 1024 * 100)
                        {
                            // 接收的數據太大,則顯示「數據接收成功」
                            Response.Write("數據接收成功");
                        }
                        else
                        {
                            // 顯示接收到的數據
                            string body = reader.ReadToEnd();
                            Response.Write(Server.HtmlEncode(body));
                        }
                    } 
                    break;
                case "uploadFile": // 處理上傳文件的請求
                    for (int i = 0; i < Request.Files.Count; i++)
                    {
                        string key = Request.Files.GetKey(i);
                        HttpPostedFile file = Request.Files.Get(key);
                        string savePath = @"d:\" + file.FileName;

                        // 保存文件
                        file.SaveAs(savePath);

                        Response.Write(string.Format("key: {0}, fileName: {1}, savePath: {2}", key, file.FileName, savePath));
                        Response.Write("\n");
                    }
                    break;
                case "outputCookie": // 用於顯示服務端獲取到的 cookie 信息
                    for (int i = 0; i < Request.Cookies.Count; i++)
                    {
                        HttpCookie cookie = Request.Cookies[0];
                        Response.Write(string.Format("cookieName: {0}, cookieValue: {1}", cookie.Name, cookie.Value));
                        Response.Write("\n");
                    }
                    break;
                case "outputCustomHeader": // 用於顯示一個自定義的 http header
                    Response.Write("myRequestHeader: " + Request.Headers["myRequestHeader"]);
                    break;
                default:
                    break;
            }

            Response.End();
        }
    }
}


一、演示新的 HttpClient
Summary.xaml.csweb

/*
 * 本例簡要說明新的命名空間 Windows.Web.Http 下的新的 HttpClient 的用法(其餘相關類也均來自新的 Windows.Web.Http 命名空間)
 * 經過 HttpClient, HttpRequestMessage, HttpResponseMessage 實現 HTTP 通訊
 * 
 * 
 * 在 win8.1 中加強了 HttpClient 的功能並將此加強版的 HttpClient 轉移至了 Windows.Web.Http 命名空間下(原 win8 的 HttpClient 在 System.Net.Http 命名空間下,依舊可用)
 * 一、若是要查看 System.Net.Http 命名空間下的 HttpClient 的用法請參見:http://www.cnblogs.com/webabcd/archive/2013/09/23/3334233.html
 * 二、關於支持 OAuth 2.0 驗證的客戶端也請參見:http://www.cnblogs.com/webabcd/archive/2013/09/23/3334233.html
 * 
 * 
 * HttpClient - 用於發起 http 請求,以及接收 http 響應
 *     GetStringAsync(), GetAsync(), GetBufferAsync(), GetInputStreamAsync() - http get 請求
 *     DeleteAsync() - http delete 請求
 *     PostAsync(), PutAsync() - http post/put 請求
 *         參數:IHttpContent content - http 請求的數據
 *             實現了 IHttpContent 的類有:HttpStringContent, HttpBufferContent, HttpStreamContent, HttpFormUrlEncodedContent, HttpMultipartFormDataContent 等
 *         參數:HttpCompletionOption completionOption(HttpCompletionOption 枚舉)
 *             ResponseContentRead - 獲取到所有內容後再返回數據,默認值
 *             ResponseHeadersRead - 獲取到頭信息後就返回數據,用於流式獲取
 *     SendRequestAsync() - 根據指定的 HttpRequestMessage 對象發起請求
 * 
 * HttpRequestMessage - http 請求
 *     Method - http 方法
 *     RequestUri - 請求的 uri
 *     Headers - http 的請求頭信息
 *     Properties - 當作上下文用
 *     Content - http 請求的內容(IHttpContent 類型)
 *         實現了 IHttpContent 的類有:HttpStringContent, HttpBufferContent, HttpStreamContent, HttpFormUrlEncodedContent, HttpMultipartFormDataContent 等
 *     TransportInformation - 獲取一個 HttpTransportInformation 類型的對象,用於 https 相關
 *         
 * HttpResponseMessage - http 響應
 *     RequestMessage - 對應的 HttpRequestMessage 對象
 *     Headers - http 的響應頭信息
 *     Version - http 版本,默認是 1.1
 *     Source - 數據來源(HttpResponseMessageSource 枚舉:Cache 或 Network)
 *     StatusCode - http 響應的狀態碼
 *     ReasonPhrase - http 響應的狀態碼所對應的短語
 *     IsSuccessStatusCode - http 響應的狀態碼是不是成功的值(200-299)
 *     EnsureSuccessStatusCode() - 當 IsSuccessStatusCode 爲 false 時會拋出異常
 *     
 * 
 * 另:
 * win8 metro 的 http 抓包可用 fiddler
 * 
 * 還有:
 * http 通訊還能夠經過以下方法實現
 * HttpWebRequest webRequest = WebRequest.Create(url);
 */

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using Windows.Web.Http;

namespace Windows81.Communication.HTTP
{
    public sealed partial class Summary : Page
    {
        private HttpClient _httpClient;
        private CancellationTokenSource _cts;

        public Summary()
        {
            this.InitializeComponent();
        }

        protected override void OnNavigatedFrom(NavigationEventArgs e)
        {
            // 釋放資源
            if (_httpClient != null)
            {
                _httpClient.Dispose();
                _httpClient = null;
            }

            if (_cts != null)
            {
                _cts.Dispose();
                _cts = null;
            }
        }

        private async void btnPost_Click(object sender, RoutedEventArgs e)
        {
            _httpClient = new HttpClient();
            _cts = new CancellationTokenSource();

            try
            {
                string url = "http://localhost:39630/HttpDemo.aspx?action=postString";
                // 建立一個 HttpRequestMessage 對象
                HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, new Uri(url));

                // 須要 post 的數據
                HttpFormUrlEncodedContent postData = new HttpFormUrlEncodedContent(
                    new List<KeyValuePair<string, string>>
                    {
                        new KeyValuePair<string, string>("param1", "web"),
                        new KeyValuePair<string, string>("param2", "abcd")
                    }
                );

                // http 請求的數據
                request.Content = postData;
                // http 請求的頭信息(嘰歪一個,終於把 Referrer 改爲 Referer 了)
                request.Headers.Referer = new Uri("http://webabcd.cnblogs.com");

                // 請求 HttpRequestMessage 對象,並返回 HttpResponseMessage 數據
                HttpResponseMessage response = await _httpClient.SendRequestAsync(request).AsTask(_cts.Token); // 取消請求的方式改成經過 CancellationTokenSource 來實現了

                // http 響應的狀態碼及其對應的短語
                lblMsg.Text += ((int)response.StatusCode) + " " + response.ReasonPhrase;
                lblMsg.Text += Environment.NewLine;

                // 以字符串的方式獲取響應數據
                lblMsg.Text += await response.Content.ReadAsStringAsync();
                lblMsg.Text += Environment.NewLine;
            }
            catch (TaskCanceledException)
            {
                lblMsg.Text += "取消了";
                lblMsg.Text += Environment.NewLine;
            }
            catch (Exception ex)
            {
                lblMsg.Text += ex.ToString();
                lblMsg.Text += Environment.NewLine;
            }
        }

        private void btnCancel_Click(object sender, RoutedEventArgs e)
        {
            // 取消 http 請求
            if (_cts != null)
            {
                _cts.Cancel();
                _cts.Dispose();
                _cts = null;
            }
        }
    }
}


二、演示 http get string
GetString.xaml.cswindows

/*
 * 演示 http get string
 */

using System;
using System.Threading;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using Windows.Web.Http;

namespace Windows81.Communication.HTTP
{
    public sealed partial class GetString : Page
    {
        private HttpClient _httpClient;
        private CancellationTokenSource _cts;

        public GetString()
        {
            this.InitializeComponent();
        }

        protected override void OnNavigatedFrom(NavigationEventArgs e)
        {
            // 釋放資源
            if (_httpClient != null)
            {
                _httpClient.Dispose();
                _httpClient = null;
            }

            if (_cts != null)
            {
                _cts.Dispose();
                _cts = null;
            }
        }

        private async void btnGetString_Click(object sender, RoutedEventArgs e)
        {
            _httpClient = new HttpClient();
            _cts = new CancellationTokenSource();

            try
            {
                HttpResponseMessage response = await _httpClient.GetAsync(new Uri("http://localhost:39630/HttpDemo.aspx?action=getString")).AsTask(_cts.Token); // 取消請求的方式改成經過 CancellationTokenSource 來實現了

                lblMsg.Text += ((int)response.StatusCode) + " " + response.ReasonPhrase;
                lblMsg.Text += Environment.NewLine;

                // IHttpContent.ReadAsStringAsync() - 獲取 string 類型的響應數據
                // IHttpContent.ReadAsBufferAsync() - 獲取 IBuffer 類型的響應數據
                // IHttpContent.ReadAsInputStreamAsync() - 獲取 IInputStream 類型的響應數據
                lblMsg.Text += await response.Content.ReadAsStringAsync();
                lblMsg.Text += Environment.NewLine;
            }
            catch (TaskCanceledException)
            {
                lblMsg.Text += "取消了";
                lblMsg.Text += Environment.NewLine;
            }
            catch (Exception ex)
            {
                lblMsg.Text += ex.ToString();
                lblMsg.Text += Environment.NewLine;
            }
        }

        private void btnCancel_Click(object sender, RoutedEventArgs e)
        {
            // 取消 http 請求
            if (_cts != null)
            {
                _cts.Cancel();
                _cts.Dispose();
                _cts = null;
            }
        }
    }
}


三、演示 http get stream
GetStream.xaml.cscookie

/*
 * 演示 http get stream
 */

using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Windows.Security.Cryptography;
using Windows.Storage.Streams;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using Windows.Web.Http;

namespace Windows81.Communication.HTTP
{
    public sealed partial class GetStream : Page
    {
        private HttpClient _httpClient;
        private CancellationTokenSource _cts;

        public GetStream()
        {
            this.InitializeComponent();
        }

        protected override void OnNavigatedFrom(NavigationEventArgs e)
        {
            // 釋放資源
            if (_httpClient != null)
            {
                _httpClient.Dispose();
                _httpClient = null;
            }

            if (_cts != null)
            {
                _cts.Dispose();
                _cts = null;
            }
        }

        private async void btnGetStream_Click(object sender, RoutedEventArgs e)
        {
            _httpClient = new HttpClient();
            _cts = new CancellationTokenSource();

            try
            {
                // HttpCompletionOption.ResponseHeadersRead - 獲取到頭信息後就返回數據,用於流式獲取
                HttpResponseMessage response = await _httpClient.GetAsync(
                    new Uri("http://localhost:39630/HttpDemo.aspx?action=getStream"),
                    HttpCompletionOption.ResponseHeadersRead).AsTask(_cts.Token); // 取消請求的方式改成經過 CancellationTokenSource 來實現了

                lblMsg.Text += ((int)response.StatusCode) + " " + response.ReasonPhrase;
                lblMsg.Text += Environment.NewLine;

                // IHttpContent.ReadAsStringAsync() - 獲取 string 類型的響應數據
                // IHttpContent.ReadAsBufferAsync() - 獲取 IBuffer 類型的響應數據
                // IHttpContent.ReadAsInputStreamAsync() - 獲取 IInputStream 類型的響應數據
                using (Stream responseStream = (await response.Content.ReadAsInputStreamAsync()).AsStreamForRead())
                {
                    byte[] buffer = new byte[32];
                    int read = 0;

                    while ((read = await responseStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
                    {
                        lblMsg.Text += "讀取的字節數: " + read.ToString();
                        lblMsg.Text += Environment.NewLine;

                        IBuffer responseBuffer = CryptographicBuffer.CreateFromByteArray(buffer);
                        lblMsg.Text += CryptographicBuffer.EncodeToHexString(responseBuffer);
                        lblMsg.Text += Environment.NewLine;

                        buffer = new byte[32];
                    }
                }
            }
            catch (TaskCanceledException)
            {
                lblMsg.Text += "取消了";
                lblMsg.Text += Environment.NewLine;
            }
            catch (Exception ex)
            {
                lblMsg.Text += ex.ToString();
                lblMsg.Text += Environment.NewLine;
            }
        }

        private void btnCancel_Click(object sender, RoutedEventArgs e)
        {
            // 取消 http 請求
            if (_cts != null)
            {
                _cts.Cancel();
                _cts.Dispose();
                _cts = null;
            }
        }
    }
}


四、演示 http post string
PostString.xaml.csapp

/*
 * 演示 http post string
 */

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using Windows.Web.Http;

namespace Windows81.Communication.HTTP
{
    public sealed partial class PostString : Page
    {
        private HttpClient _httpClient;
        private CancellationTokenSource _cts;

        public PostString()
        {
            this.InitializeComponent();
        }

        protected override void OnNavigatedFrom(NavigationEventArgs e)
        {
            // 釋放資源
            if (_httpClient != null)
            {
                _httpClient.Dispose();
                _httpClient = null;
            }

            if (_cts != null)
            {
                _cts.Dispose();
                _cts = null;
            }
        }

        private async void btnPostString_Click(object sender, RoutedEventArgs e)
        {
            _httpClient = new HttpClient();
            _cts = new CancellationTokenSource();

            try
            {
                // 須要 post 的數據
                var postData = new HttpFormUrlEncodedContent(
                    new List<KeyValuePair<string, string>>
                    {
                        new KeyValuePair<string, string>("param1", "web"),
                        new KeyValuePair<string, string>("param2", "abcd")
                    }
                );

                HttpResponseMessage response = await _httpClient.PostAsync(
                    new Uri("http://localhost:39630/HttpDemo.aspx?action=postString"),
                    postData).AsTask(_cts.Token); // 取消請求的方式改成經過 CancellationTokenSource 來實現了

                lblMsg.Text += ((int)response.StatusCode) + " " + response.ReasonPhrase;
                lblMsg.Text += Environment.NewLine;

                // HttpContent.ReadAsStringAsync() - 以 string 方式獲取響應數據
                // HttpContent.ReadAsByteArrayAsync() - 以 byte[] 方式獲取響應數據
                // HttpContent.ReadAsStreamAsync() - 以 stream 方式獲取響應數據
                lblMsg.Text += await response.Content.ReadAsStringAsync();
                lblMsg.Text += Environment.NewLine;
            }
            catch (TaskCanceledException)
            {
                lblMsg.Text += "取消了";
                lblMsg.Text += Environment.NewLine;
            }
            catch (Exception ex)
            {
                lblMsg.Text += ex.ToString();
                lblMsg.Text += Environment.NewLine;
            }
        }

        private void btnCancel_Click(object sender, RoutedEventArgs e)
        {
            // 取消 http 請求
            if (_cts != null)
            {
                _cts.Cancel();
                _cts.Dispose();
                _cts = null;
            }
        }
    }
}


五、演示 http post stream
PostStream.xaml.csasp.net

/*
 * 演示 http post stream
 */

using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using Windows.Web.Http;

namespace Windows81.Communication.HTTP
{
    public sealed partial class PostStream : Page
    {
        private HttpClient _httpClient;
        private CancellationTokenSource _cts;

        public PostStream()
        {
            this.InitializeComponent();
        }

        protected override void OnNavigatedFrom(NavigationEventArgs e)
        {
            // 釋放資源
            if (_httpClient != null)
            {
                _httpClient.Dispose();
                _httpClient = null;
            }

            if (_cts != null)
            {
                _cts.Dispose();
                _cts = null;
            }
        }

        private async void btnPostStream_Click(object sender, RoutedEventArgs e)
        {
            _httpClient = new HttpClient();
            _cts = new CancellationTokenSource();

            try
            {
                // 須要 post 的 stream 數據
                Stream stream = GenerateSampleStream(128);
                HttpStreamContent streamContent = new HttpStreamContent(stream.AsInputStream());

                HttpResponseMessage response = await _httpClient.PostAsync(
                   new Uri("http://localhost:39630/HttpDemo.aspx?action=postStream"),
                   streamContent).AsTask(_cts.Token);// 取消請求的方式改成經過 CancellationTokenSource 來實現了

                lblMsg.Text += ((int)response.StatusCode) + " " + response.ReasonPhrase;
                lblMsg.Text += Environment.NewLine;

                // IHttpContent.ReadAsStringAsync() - 獲取 string 類型的響應數據
                // IHttpContent.ReadAsBufferAsync() - 獲取 IBuffer 類型的響應數據
                // IHttpContent.ReadAsInputStreamAsync() - 獲取 IInputStream 類型的響應數據
                lblMsg.Text += await response.Content.ReadAsStringAsync();
                lblMsg.Text += Environment.NewLine;
            }
            catch (TaskCanceledException)
            {
                lblMsg.Text += "取消了";
                lblMsg.Text += Environment.NewLine;
            }
            catch (Exception ex)
            {
                lblMsg.Text += ex.ToString();
                lblMsg.Text += Environment.NewLine;
            }
        }

        // 生成一個指定大小的內存流
        private static MemoryStream GenerateSampleStream(int size)
        {
            byte[] subData = new byte[size];
            for (int i = 0; i < subData.Length; i++)
            {
                subData[i] = (byte)(97 + i % 26); // a-z
            }

            return new MemoryStream(subData);
        }

        private void btnCancel_Click(object sender, RoutedEventArgs e)
        {
            // 取消 http 請求
            if (_cts != null)
            {
                _cts.Cancel();
                _cts.Dispose();
                _cts = null;
            }
        }
    }
}



OK
[源碼下載]async

相關文章
相關標籤/搜索