[源码下载]

重新想象 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(); 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 > * )
{
// 接收的数据太大,则显示“数据接收成功”
Response.Write("数据接收成功");
}
else
{
// 显示接收到的数据
string body = reader.ReadToEnd();
Response.Write(Server.HtmlEncode(body));
}
}
break;
case "uploadFile": // 处理上传文件的请求
for (int i = ; 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 = ; i < Request.Cookies.Count; i++)
{
HttpCookie cookie = Request.Cookies[];
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();
}
}
}

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 = ;
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 = ; i < subData.Length; i++)
{
subData[i] = (byte)( + i % ); // 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 = ;
} 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 = ; i < count; i++)
{
data[i] = ;
} // 延迟 10 毫秒再继续,以模拟一个比较慢的输入流
await Task.Delay(); 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
[源码下载]

重新想象 Windows 8.1 Store Apps (89) - 通信的新特性: 下载数据, 上传数据, 上传文件的更多相关文章

  1. 重新想象 Windows 8.1 Store Apps (88) - 通信的新特性: 新的 HttpClient

    [源码下载] 重新想象 Windows 8.1 Store Apps (88) - 通信的新特性: 新的 HttpClient 作者:webabcd 介绍重新想象 Windows 8.1 Store ...

  2. 重新想象 Windows 8.1 Store Apps (90) - 通信的新特性: 通过 HttpBaseProtocolFilter 实现 http 请求的缓存控制,以及 cookie 读写; 自定义 HttpFilter; 其他

    [源码下载] 重新想象 Windows 8.1 Store Apps (90) - 通信的新特性: 通过 HttpBaseProtocolFilter 实现 http 请求的缓存控制,以及 cooki ...

  3. 重新想象 Windows 8.1 Store Apps (91) - 后台任务的新特性: 下载和上传的新特性, 程序启动前预下载网络资源, 后台任务的其它新特性

    [源码下载] 重新想象 Windows 8.1 Store Apps (91) - 后台任务的新特性: 下载和上传的新特性, 程序启动前预下载网络资源, 后台任务的其它新特性 作者:webabcd 介 ...

  4. 重新想象 Windows 8.1 Store Apps (83) - 文件系统的新特性

    [源码下载] 重新想象 Windows 8.1 Store Apps (83) - 文件系统的新特性 作者:webabcd 介绍重新想象 Windows 8.1 Store Apps 之文件系统的新特 ...

  5. 重新想象 Windows 8.1 Store Apps (84) - 图像处理的新特性, Share Contract 的新特性

    [源码下载] 重新想象 Windows 8.1 Store Apps (84) - 图像处理的新特性, Share Contract 的新特性 作者:webabcd 介绍重新想象 Windows 8. ...

  6. 重新想象 Windows 8.1 Store Apps (80) - 控件增强: WebView 之基本应用, POST 数据, 与 JavaScript 交互

    [源码下载] 重新想象 Windows 8.1 Store Apps (80) - 控件增强: WebView 之基本应用, POST 数据, 与 JavaScript 交互 作者:webabcd 介 ...

  7. 重新想象 Windows 8.1 Store Apps 系列文章索引

    [源码下载] [重新想象 Windows 8 Store Apps 系列文章] 重新想象 Windows 8.1 Store Apps 系列文章索引 作者:webabcd 1.重新想象 Windows ...

  8. 重新想象 Windows 8.1 Store Apps (85) - 警报通知(闹钟), Tile 的新特性

    [源码下载] 重新想象 Windows 8.1 Store Apps (85) - 警报通知(闹钟), Tile 的新特性 作者:webabcd 介绍重新想象 Windows 8.1 Store Ap ...

  9. 重新想象 Windows 8.1 Store Apps (81) - 控件增强: WebView 之加载本地 html, 智能替换 html 中的 url 引用, 通过 Share Contract 分享 WebView 中的内容, 为 WebView 截图

    [源码下载] 重新想象 Windows 8.1 Store Apps (81) - 控件增强: WebView 之加载本地 html, 智能替换 html 中的 url 引用, 通过 Share Co ...

随机推荐

  1. 【css3】如何自定义 placeholder 文本颜色

    昨天写了一篇基于 jquery 实现 ie 浏览器兼容 placeholder 效果,具体内容点击传送门.不过还是有点小瑕疵,就是不能设置 placeholder 文本颜色.本文主要介绍利用 css ...

  2. 写essay和research paper必用的17个网站

    1.http://scholar.google.com/ 虽然还是Beta版,但个人已觉得现在已经是很好很强大了,Google学术搜索滤掉了普通搜索结果中大量的垃圾信息,排列出文章的不同版本以及被其它 ...

  3. cordova混合开发:Android中native调用javascript

    今天学习怎么在java中调用javascript方法,做个记录: 第一种方式,这个最简单: loadUrl("javascript:func1()"); 要注意要在devicere ...

  4. 学习之路三十六:SQL知识总结 - [游标||字符串分割]

    好久没有写文章了,今天把前不久项目用到的SQL知识总结一下. 一丶字符串分割 SQL内置函数中是没有Split分割函数的,所以需要自己去实现,不多说,上代码: )) RETURNS @result T ...

  5. 如何做好IT运营.

    定义IT管理的重点在于业务策略与 IT 部门提供的服务之间的一致性.IT 管理可建立必要的管理机制来确保可预测的 IT 服务交付,从而确保业务流程和 IT 流程之间的联系.IT 管理传统上属于CIO. ...

  6. Visual Studio 2015 开发大量 JavaScript 代码项目程序崩溃的解决方案

    最近公司做新项目,基于 Bootstrap.AngularJS 和 kendo 开发一套后台的管理系统,在项目中使用了大量的 JavaScript 文件,这两天 Visual Studio 2015 ...

  7. RDLC报表 在WinForm里运行出现 未能加载文件或程序集microsoft.reportviewer.winforms

    做一下记录顺便帮助一下遇到问题的朋友. 做RDLC报表在WinForm运行,在VS里面调试引用了“Microsoft.ReportViewer.Common.dll”和“Microsoft.Repor ...

  8. SLAM拾萃(3):siftGPU

    前言 本周博客我们给大家介绍一下SiftGPU.由于特征匹配是SLAM中非常耗时间的一步,许多人都想把它的时间降至最短,因此目前ORB成了非常受欢迎的特征.而老牌SIFT,则一直给人一种“很严谨很精确 ...

  9. ubuntu 安装bochs

    //首先官网下载bochs源码wget http://bochs.sourceforge.net/svn-snapshot/bochs-20150503.tar.gz//然后解压 tar vxzf b ...

  10. sql server还原数据库bak文件

    RESTORE DATABASE CCC FROM DISK = 'AAA.bak' with replace,  MOVE 'BBB' TO 'C:\Program Files\Microsoft ...