重新想象 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) - 通信的新特性: 下载数据, 上传数据, 上传文件的更多相关文章
- 重新想象 Windows 8.1 Store Apps (88) - 通信的新特性: 新的 HttpClient
[源码下载] 重新想象 Windows 8.1 Store Apps (88) - 通信的新特性: 新的 HttpClient 作者:webabcd 介绍重新想象 Windows 8.1 Store ...
- 重新想象 Windows 8.1 Store Apps (90) - 通信的新特性: 通过 HttpBaseProtocolFilter 实现 http 请求的缓存控制,以及 cookie 读写; 自定义 HttpFilter; 其他
[源码下载] 重新想象 Windows 8.1 Store Apps (90) - 通信的新特性: 通过 HttpBaseProtocolFilter 实现 http 请求的缓存控制,以及 cooki ...
- 重新想象 Windows 8.1 Store Apps (91) - 后台任务的新特性: 下载和上传的新特性, 程序启动前预下载网络资源, 后台任务的其它新特性
[源码下载] 重新想象 Windows 8.1 Store Apps (91) - 后台任务的新特性: 下载和上传的新特性, 程序启动前预下载网络资源, 后台任务的其它新特性 作者:webabcd 介 ...
- 重新想象 Windows 8.1 Store Apps (83) - 文件系统的新特性
[源码下载] 重新想象 Windows 8.1 Store Apps (83) - 文件系统的新特性 作者:webabcd 介绍重新想象 Windows 8.1 Store Apps 之文件系统的新特 ...
- 重新想象 Windows 8.1 Store Apps (84) - 图像处理的新特性, Share Contract 的新特性
[源码下载] 重新想象 Windows 8.1 Store Apps (84) - 图像处理的新特性, Share Contract 的新特性 作者:webabcd 介绍重新想象 Windows 8. ...
- 重新想象 Windows 8.1 Store Apps (80) - 控件增强: WebView 之基本应用, POST 数据, 与 JavaScript 交互
[源码下载] 重新想象 Windows 8.1 Store Apps (80) - 控件增强: WebView 之基本应用, POST 数据, 与 JavaScript 交互 作者:webabcd 介 ...
- 重新想象 Windows 8.1 Store Apps 系列文章索引
[源码下载] [重新想象 Windows 8 Store Apps 系列文章] 重新想象 Windows 8.1 Store Apps 系列文章索引 作者:webabcd 1.重新想象 Windows ...
- 重新想象 Windows 8.1 Store Apps (85) - 警报通知(闹钟), Tile 的新特性
[源码下载] 重新想象 Windows 8.1 Store Apps (85) - 警报通知(闹钟), Tile 的新特性 作者:webabcd 介绍重新想象 Windows 8.1 Store Ap ...
- 重新想象 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 ...
随机推荐
- [转]Raspberry Pi做成路由器
http://raspjason.blog.51cto.com/8565009/1426561/ 曾经看到很多文章把Raspberry Pi制作成无线AP,但是我今天要做的是把Raspberry Pi ...
- [原]OpenGL基础教程(二)多边形绘制
上篇介绍了最基本的三角形绘制,本篇介绍如何使用索引的方式绘制多边行. 为什么要使用索引方式,总体来说提高性能.如何提高:使用顶点数组的好处是避免大量的函数调用.即避免每画一个顶点就调用1次glVert ...
- OceanBase RPC机制简要说明
http://note.youdao.com/share/?id=d2163a7ba8ec1ec58e64683a961c5121&type=note RPC是OB一个比较重要的各个组件间进行 ...
- saiku 分布式实践
saiku比较吃内存,一旦人多了,那么内存可能不够,所以会考虑主从结构,分担压力.为了保证数据的稳定性,也会有类似的考虑,那么问题来了,如何实现saiku的分布式搭建哪? 我阅读了一些国内的文章,没有 ...
- NetBPM的安装 -转
NetBPM的安装还是比较简单的,有比较详细的文档. 1.当然是先下载运行程序了, netbpm-0.8.3.1.zip ,官方网站:http://www.netbpm.org:2.然后解压后自己看 ...
- 使用SharePoint Designer定制开发专家库系统实例!
将近大半年都没有更新博客了,趁这段时间不忙,后续会继续分享一些技术和实际应用.对于Sharepoint的定制开发有很多种方式,对于一般的应用系统,可以使用Sharepoint本身自带的功能,如列表作为 ...
- php的单例模式
据说,单例模式是设计模式中最简单的一种. 不多说,先上代码,然后解说,一共两个文件: danli.class <?php class Danli { //保存类的实例的静态成员变量 static ...
- MFC ADO连接Oracle12c数据库 客户端环境搭建
ADO连接方式一:Provider=MSDAORA.1; 环境配置如下: 去官网下载ODAC121024Xcopy_32bit.zip安装 安装方式如下: (1)解压文件 (2)用命令行CD到该文件的 ...
- Android通过编码实现GPS开关
在Android 2.2以后才可使用 import android.content.ContentResolver; import android.content.Context; import an ...
- WP8 SqlCE和SqlLite数据存储性能比较
在平时的开发中一定会用到本地数据存储,除了独立存储外我们还可以选择SqlCE和SqlLite:于是在选择上我们就必须权衡他们两者的性能择优选择. 测试代码:(这个例子是在msdn sqllite例子上 ...