重新想象 Windows 8.1 Store Apps (89) - 通信的新特性: 下載數據, 上傳數據, 上傳文件
原文:重新想象 Windows 8.1 Store Apps (89) - 通信的新特性: 下載數據, 上傳數據, 上傳文件
[源碼下載]
重新想象 Windows 8.1 Store Apps (89) - 通信的新特性: 下載數據, 上傳數據, 上傳文件
作者:webabcd
介紹
重新想象 Windows 8.1 Store Apps 之通信的新特性
- 下載數據(顯示下載進度,將下載數據保存到本地)
- 上傳數據(顯示上傳進度)
- 上傳文件
示例
HTTP 服務端
WebServer/HttpDemo.aspx.cs
/** 用于響應 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 headerResponse.Write("myRequestHeader: " + Request.Headers["myRequestHeader"]);break;default:break;}Response.End();}} }
1、演示如何通過新的 HttpClient(Windows.Web.Http)獲取下載進度,并將下載數據保存到本地
Download.xaml.cs
/** 本例演示如何通過新的 HttpClient(Windows.Web.Http)獲取下載進度,并將下載數據保存到本地* * * 注:在 win8 時代要想獲取下載進度只能依靠后臺任務來完成*/using System; using System.Threading; using System.Threading.Tasks; using Windows.Storage; 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 Download : Page{private HttpClient _httpClient;private CancellationTokenSource _cts;public Download(){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 btnDownload_Click(object sender, RoutedEventArgs e){_httpClient = new HttpClient();_cts = new CancellationTokenSource();try{// 用于獲取下載進度IProgress<HttpProgress> progress = new Progress<HttpProgress>(ProgressHandler);HttpResponseMessage response = await _httpClient.GetAsync(new Uri("http://files.cnblogs.com/webabcd/WindowsPhone.rar?ll"),HttpCompletionOption.ResponseContentRead).AsTask(_cts.Token, progress); // 把 progress 放到 task 里,以便獲取下載進度 lblMsg.Text += ((int)response.StatusCode) + " " + response.ReasonPhrase;lblMsg.Text += Environment.NewLine;// 將下載好的數據保存到本地StorageFolder storageFolder = KnownFolders.DocumentsLibrary;StorageFile storageFile = await storageFolder.CreateFileAsync("WindowsPhone.rar", CreationCollisionOption.ReplaceExisting);using (StorageStreamTransaction transaction = await storageFile.OpenTransactedWriteAsync()){lblMsg.Text = "文件已下載,寫入到磁盤中...";/** IHttpContent.WriteToStreamAsync() - 用于保存數據*/await response.Content.WriteToStreamAsync(transaction.Stream);await transaction.CommitAsync();lblMsg.Text = "文件已寫入到磁盤";}}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;}}// 下載進度發生變化時調用的處理器private void ProgressHandler(HttpProgress progress){/** HttpProgress - http 通信的進度* BytesReceived - 已收到的字節數* BytesSent - 已發送的字節數* TotalBytesToReceive - 總共需要收到的字節數* TotalBytesToSend - 總共需要發送的字節數* Retries - 重試次數* Stage - 當前通信的階段(HttpProgressStage 枚舉)*/string result = "BytesReceived: {0}\nBytesSent: {1}\nRetries: {2}\nStage: {3}\nTotalBytesToReceive: {4}\nTotalBytesToSend: {5}\n";result = string.Format(result, progress.BytesReceived, progress.BytesSent, progress.Retries, progress.Stage, progress.TotalBytesToReceive, progress.TotalBytesToSend);lblMsg.Text = result;}} }
2、演示如何通過新的 HttpClient(Windows.Web.Http)獲取上傳進度
Upload.xaml.cs
/** 本例演示如何通過新的 HttpClient(Windows.Web.Http)獲取上傳進度* * * 注:在 win8 時代要想獲取上傳進度只能依靠后臺任務來完成*/using System; using System.IO; using System.Runtime.InteropServices.WindowsRuntime; using System.Threading; using System.Threading.Tasks; using Windows.Foundation; 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 Upload : Page{private HttpClient _httpClient;private CancellationTokenSource _cts;public Upload(){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 btnUpload_Click(object sender, RoutedEventArgs e){_httpClient = new HttpClient();_cts = new CancellationTokenSource();try{Uri resourceAddress = new Uri("http://localhost:39630/HttpDemo.aspx?action=postStream");// 模擬一個比較大的比較慢的流,供 http 上傳const uint streamLength = 10000000;HttpStreamContent streamContent = new HttpStreamContent(new SlowInputStream(streamLength));streamContent.Headers.ContentLength = streamLength; // 必須要指定請求數據的 ContentLength,否則就是 chunked 了// 用于獲取上傳進度IProgress<HttpProgress> progress = new Progress<HttpProgress>(ProgressHandler);HttpResponseMessage response = await _httpClient.PostAsync(resourceAddress, streamContent).AsTask(_cts.Token, progress); // 把 progress 放到 task 里,以便獲取上傳進度 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 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;}}// 上傳進度發生變化時調用的處理器private void ProgressHandler(HttpProgress progress){/** HttpProgress - http 通信的進度* BytesReceived - 已收到的字節數* BytesSent - 已發送的字節數* TotalBytesToReceive - 總共需要收到的字節數* TotalBytesToSend - 總共需要發送的字節數* Retries - 重試次數* Stage - 當前通信的階段(HttpProgressStage 枚舉)*/string result = "BytesReceived: {0}\nBytesSent: {1}\nRetries: {2}\nStage: {3}\nTotalBytesToReceive: {4}\nTotalBytesToSend: {5}\n";result = string.Format(result, progress.BytesReceived, progress.BytesSent, progress.Retries, progress.Stage, progress.TotalBytesToReceive, progress.TotalBytesToSend);lblMsg.Text = result;}}// 模擬一個比較慢的輸入流class SlowInputStream : IInputStream{uint length;uint position;public SlowInputStream(uint length){this.length = length;position = 0;}public IAsyncOperationWithProgress<IBuffer, uint> ReadAsync(IBuffer buffer, uint count, InputStreamOptions options){return AsyncInfo.Run<IBuffer, uint>(async (cancellationToken, progress) =>{if (length - position < count){count = length - position;}byte[] data = new byte[count];for (uint i = 0; i < count; i++){data[i] = 64;}// 延遲 10 毫秒再繼續,以模擬一個比較慢的輸入流await Task.Delay(10);position += count;progress.Report(count);return data.AsBuffer();});}public void Dispose(){}} }
3、演示如何通過新的 HttpClient(Windows.Web.Http)上傳文件(通過 multipart/form-data 的方式)
UploadFile.xaml.cs
/** 本例演示如何通過新的 HttpClient(Windows.Web.Http)上傳文件(通過 multipart/form-data 的方式)*/using System; using System.Threading; using System.Threading.Tasks; using Windows.Storage; 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 UploadFile : Page{private HttpClient _httpClient;private CancellationTokenSource _cts;public UploadFile(){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 btnUploadFile_Click(object sender, RoutedEventArgs e){_httpClient = new HttpClient();_cts = new CancellationTokenSource();try{// 構造需要上傳的文件數據StorageFile file1 = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/Son.jpg", UriKind.Absolute));IRandomAccessStreamWithContentType stream1 = await file1.OpenReadAsync();HttpStreamContent streamContent1 = new HttpStreamContent(stream1);// 構造需要上傳的文件數據StorageFile file2 = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/Son.jpg", UriKind.Absolute));IRandomAccessStreamWithContentType stream2 = await file1.OpenReadAsync();HttpStreamContent streamContent2 = new HttpStreamContent(stream2);// 通過 HttpMultipartFormDataContent 來指定需要“multipart/form-data”上傳的文件HttpMultipartFormDataContent fileContent = new HttpMultipartFormDataContent();// 第 1 個參數:需要上傳的文件數據// 第 2 個參數:對應 asp.net 服務的 Request.Files 中的 key(參見:WebServer 項目中的 HttpDemo.aspx.cs)// 第 3 個參數:對應 asp.net 服務的 Request.Files 中的 fileName(參見:WebServer 項目中的 HttpDemo.aspx.cs)fileContent.Add(streamContent1, "file1", "file1.jpg"); fileContent.Add(streamContent2, "file2", "file2.jpg");HttpResponseMessage response = await _httpClient.PostAsync(new Uri("http://localhost:39630/HttpDemo.aspx?action=uploadFile"), fileContent).AsTask(_cts.Token);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;}}} }
OK
[源碼下載]
posted on 2014-09-23 13:46 NET未來之路 閱讀(...) 評論(...) 編輯 收藏