设为首页 收藏本站
查看: 741|回复: 0

重新想象 Windows 8 Store Apps (66)

[复制链接]

尚未签到

发表于 2015-5-22 07:28:04 | 显示全部楼层 |阅读模式
  [源码下载]




重新想象 Windows 8 Store Apps (66) - 后台任务: 下载和上传  
作者:webabcd

介绍
重新想象 Windows 8 Store Apps 之 后台任务


  • 后台下载任务
  • 后台上传任务
  
示例
扩展了 DownloadOperation 和 UploadOperation,以便下载进度或上传进度可通知
BackgroundTask/TransferModel.cs



/*
* 扩展了 DownloadOperation 和 UploadOperation,以便下载进度或上传进度可通知
*/
using System;
using System.ComponentModel;
using Windows.Networking.BackgroundTransfer;
namespace XamlDemo.BackgroundTask
{
public class TransferModel : INotifyPropertyChanged
{
public DownloadOperation DownloadOperation { get; set; }
public UploadOperation UploadOperation { get; set; }
public string Source { get; set; }
public string Destination { get; set; }
private string _progress;
public string Progress
{
get { return _progress; }
set
{
_progress = value;
RaisePropertyChanged("Progress");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string name)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
}
}
  
1、演示后台下载任务的应用
BackgroundTask/TransferDownload.xaml



























  BackgroundTask/TransferDownload.xaml.cs



/*
* 演示后台下载任务的应用
*
* BackgroundDownloader - 后台下载任务管理器
*     CostPolicy - 下载的成本策略,BackgroundTransferCostPolicy 枚举
*         Default - 允许在高成本(比如 2G 3G)网络上传输(默认值)
*         UnrestrictedOnly - 不允许在高成本(比如 2G 3G)网络上传输
*         Always - 无论如何均可传输,即使在漫游时
*     ServerCredential - 与服务端通信时的凭据
*     ProxyCredential - 使用代理时的身份凭据
*     SetRequestHeader(string headerName, string headerValue) - 设置 http 请求头
*     CreateDownload(Uri uri, IStorageFile resultFile) - 创建一个下载任务,返回 DownloadOperation 对象
*     Group - 用于分组下载任务
*     static GetCurrentDownloadsAsync(string group) - 获取指定组下的所有下载任务
*     static GetCurrentDownloadsAsync() - 获取未与组关联的所有下载任务
*     
* DownloadOperation - 下载任务对象
*     CostPolicy - 下载的成本策略,BackgroundTransferCostPolicy 枚举
*     Group - 获取此下载任务的所属组
*     Guid - 获取此下载任务的标识
*     RequestedUri - 下载的源 URI
*     ResultFile - 下载的目标文件
*     GetResponseInformation() - 下载完成后获取到的服务端响应信息,返回 ResponseInformation 对象
*         ActualUri - 下载源的真实 URI
*         Headers - 服务端响应的 HTTP 头
*         StatusCode - 服务端响应的状态码
*     Pause() - 暂停此任务
*     Resume() - 继续此任务
*     StartAsync() - 新增一个下载任务,返回 IAsyncOperationWithProgress 对象
*     AttachAsync() - 监视已存在的下载任务,返回 IAsyncOperationWithProgress 对象
*     Progress - 获取下载进度,返回 BackgroundDownloadProgress 对象
*     
* BackgroundDownloadProgress - 后台下载任务的下载进度对象
*     BytesReceived - 已下载的字节数
*     TotalBytesToReceive - 总共需要下载的字节数,未知则为 0
*     Status - 下载状态,BackgroundTransferStatus 枚举
*         Idle, Running, PausedByApplication, PausedCostedNetwork, PausedNoNetwork, Completed, Canceled, Error
*     HasResponseChanged - 服务端响应了则为 true
*     HasRestarted - 当下载连接断掉后,系统会通过 http range 头向服务端请求断点续传,如果服务端不支持断点续传则需要重新下载,此种情况则为 true
*/
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Threading;
using System.Threading.Tasks;
using System.Linq;
using Windows.Networking.BackgroundTransfer;
using Windows.Storage;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.Web;
namespace XamlDemo.BackgroundTask
{
public sealed partial class TransferDownload : Page
{
// 下载任务的集合
private ObservableCollection _transfers = new ObservableCollection();
// 所有下载任务的关联的 CancellationTokenSource 对象
private CancellationTokenSource _cancelToken = new CancellationTokenSource();
public TransferDownload()
{
this.InitializeComponent();
Init();
}
private async void Init()
{
listView.ItemsSource = _transfers;
// 获取全部下载任务
await LoadDownloadAsync();
}
// 加载全部下载任务
private async Task LoadDownloadAsync()
{
IReadOnlyList downloads = null;
try
{
// 获取所有后台下载任务
downloads = await BackgroundDownloader.GetCurrentDownloadsAsync();
}
catch (Exception ex)
{
lblMsg.Text += ex.ToString();
lblMsg.Text += Environment.NewLine;
return;
}
if (downloads.Count > 0)
{
List tasks = new List();
foreach (DownloadOperation download in downloads)
{
// 监视指定的后台下载任务
tasks.Add(HandleDownloadAsync(download, false));
}
await Task.WhenAll(tasks);
}
}
// 新增一个下载任务
private async void btnAddDownload_Click(object sender, RoutedEventArgs e)
{
// 下载地址(注意需要在 Package.appxmanifest 中增加对 .rar 类型文件的关联)
Uri sourceUri = new Uri("http://files.iyunv.com/webabcd/Windows8.rar", UriKind.Absolute);
StorageFile destinationFile;
try
{
// 保存的目标地址
destinationFile = await KnownFolders.DocumentsLibrary.CreateFileAsync("Windows8.rar", CreationCollisionOption.GenerateUniqueName);
}
catch (Exception ex)
{
lblMsg.Text += ex.ToString();
lblMsg.Text += Environment.NewLine;
return;
}
// 创建一个后台下载任务
BackgroundDownloader backgroundDownloader = new BackgroundDownloader();
DownloadOperation download = backgroundDownloader.CreateDownload(sourceUri, destinationFile);
// 监视指定的后台下载任务
await HandleDownloadAsync(download, true);
}
///
/// 监视指定的后台下载任务
///
/// 后台下载任务
/// 是否是新增的任务
private async Task HandleDownloadAsync(DownloadOperation download, bool isNew)
{
try
{
// 将 DownloadOperation 附加到 TransferModel,以便下载进度可通知
TransferModel transfer = new TransferModel();
transfer.DownloadOperation = download;
transfer.Source = download.RequestedUri.ToString();
transfer.Destination = download.ResultFile.Path;
transfer.Progress = "0 / 0";
_transfers.Add(transfer);
lblMsg.Text += "Task Count: " + _transfers.Count.ToString();
lblMsg.Text += Environment.NewLine;
// 当下载进度发生变化时的回调函数
Progress progressCallback = new Progress(DownloadProgress);
if (isNew)
await download.StartAsync().AsTask(_cancelToken.Token, progressCallback); // 新增一个后台下载任务
else
await download.AttachAsync().AsTask(_cancelToken.Token, progressCallback); // 监视已存在的后台下载任务
// 下载完成后获取服务端的响应信息
ResponseInformation response = download.GetResponseInformation();
lblMsg.Text += "Completed: " + response.ActualUri + "-" + response.StatusCode.ToString();
lblMsg.Text += Environment.NewLine;
}
catch (TaskCanceledException) // 调用 CancellationTokenSource.Cancel() 后会抛出此异常
            {
lblMsg.Text += "Canceled: " + download.Guid;
lblMsg.Text += Environment.NewLine;
}
catch (Exception ex)
{
// 将异常转换为 WebErrorStatus 枚举,如果获取到的是 WebErrorStatus.Unknown 则说明此次异常不是涉及 web 的异常
WebErrorStatus error = BackgroundTransferError.GetStatus(ex.HResult);
lblMsg.Text += ex.ToString();
lblMsg.Text += Environment.NewLine;
}
finally
{
_transfers.Remove(_transfers.First(p => p.DownloadOperation == download));
}
}
// 进度发生变化时,更新 TransferModel 的 Progress,以便通知
private void DownloadProgress(DownloadOperation download)
{
TransferModel transfer = _transfers.First(p => p.DownloadOperation == download);
transfer.Progress = download.Progress.BytesReceived.ToString("#,0") + " / " + download.Progress.TotalBytesToReceive.ToString("#,0");
}
// 暂停全部后台下载任务
private void btnPause_Click(object sender, RoutedEventArgs e)
{
lblMsg.Text += "All Paused";
lblMsg.Text += Environment.NewLine;
foreach (TransferModel transfer in _transfers)
{
if (transfer.DownloadOperation.Progress.Status == BackgroundTransferStatus.Running)
{
transfer.DownloadOperation.Pause();
}
}
}
// 继续全部后台下载任务
private void btnResume_Click(object sender, RoutedEventArgs e)
{
lblMsg.Text += "All Resumed";
lblMsg.Text += Environment.NewLine;
foreach (TransferModel transfer in _transfers)
{
if (transfer.DownloadOperation.Progress.Status == BackgroundTransferStatus.PausedByApplication)
{
transfer.DownloadOperation.Resume();
}
}
}
// 取消全部后台下载任务
private void btnCancel_Click(object sender, RoutedEventArgs e)
{
_cancelToken.Cancel();
_cancelToken.Dispose();
_cancelToken = new CancellationTokenSource();
}
}
}
  
2、演示后台上传任务的应用
BackgroundTask/TransferUpload.xaml


























  BackgroundTask/TransferUpload.xaml.cs



/*
* 演示后台上传任务的应用
*
* BackgroundUploader - 后台上传任务管理器
*     CostPolicy - 上传的成本策略,BackgroundTransferCostPolicy 枚举
*         Default - 不允许在高成本(比如 2G 3G)网络上传输
*         UnrestrictedOnly - 允许在高成本(比如 2G 3G)网络上传输
*         Always - 无论如何均可传输,即使在漫游时
*     ServerCredential - 与服务端通信时的凭据
*     ProxyCredential - 使用代理时的身份凭据
*     SetRequestHeader(string headerName, string headerValue) - 设置 http 请求头
*     CreateUpload(Uri uri, IStorageFile sourceFile) - 创建一个上传任务,返回 UploadOperation 对象
*     CreateUploadFromStreamAsync(Uri uri, IInputStream sourceStream) - 以流的方式创建一个上传任务
*     CreateUploadAsync(Uri uri, IEnumerable parts) - 创建一个包含多个上传文件的上传任务
*     Group - 用于分组上传任务
*     static GetCurrentUploadsAsync(string group) - 获取指定组下的所有上传任务
*     static GetCurrentUploadsAsync() - 获取未与组关联的所有上传任务
*     
* UploadOperation - 上传任务对象
*     CostPolicy - 上传的成本策略,BackgroundTransferCostPolicy 枚举
*     Group - 获取此上传任务的所属组
*     Guid - 获取此上传任务的标识
*     RequestedUri - 上传任务所请求的服务端地址
*     SourceFile - 需要上传的文件,如果是一次上传多个文件则此属性为 null
*     GetResponseInformation() - 上传完成后获取到的服务端响应信息,返回 ResponseInformation 对象
*         ActualUri - 上传服务的真实 URI
*         Headers - 服务端响应的 HTTP 头
*         StatusCode - 服务端响应的状态码
*     StartAsync() - 新增一个上传任务,返回 IAsyncOperationWithProgress 对象
*     AttachAsync() - 监视已存在的上传任务,返回 IAsyncOperationWithProgress 对象
*     Progress - 获取上传进度,返回 BackgroundUploadProgress 对象
*     
* BackgroundUploadProgress - 后台上传任务的上传进度对象
*     BytesSent - 已上传的字节数
*     TotalBytesToSend - 总共需要上传的字节数
*     Status - 上传状态,BackgroundTransferStatus 枚举
*         Idle, Running, PausedByApplication, PausedCostedNetwork, PausedNoNetwork, Completed, Canceled, Error
*     HasResponseChanged - 服务端响应了则为 true
*     HasRestarted - 当上传连接断掉后,系统会重新上传,此种情况则为 true
*/
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Windows.Networking.BackgroundTransfer;
using Windows.Storage;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.Web;
namespace XamlDemo.BackgroundTask
{
public sealed partial class TransferUpload : Page
{
// 上传任务的集合
private ObservableCollection _transfers = new ObservableCollection();
// 所有上传任务的关联的 CancellationTokenSource 对象
private CancellationTokenSource _cancelToken = new CancellationTokenSource();
public TransferUpload()
{
this.InitializeComponent();
Init();
}
private async void Init()
{
listView.ItemsSource = _transfers;
// 获取全部上传任务
await LoadUploadAsync();
}
// 加载全部上传任务
private async Task LoadUploadAsync()
{
IReadOnlyList uploads = null;
try
{
// 获取所有后台上传任务
uploads = await BackgroundUploader.GetCurrentUploadsAsync();
}
catch (Exception ex)
{
lblMsg.Text += ex.ToString();
lblMsg.Text += Environment.NewLine;
return;
}
if (uploads.Count > 0)
{
List tasks = new List();
foreach (UploadOperation upload in uploads)
{
// 监视指定的后台上传任务
tasks.Add(HandleUploadAsync(upload, false));
}
await Task.WhenAll(tasks);
}
}
// 新增一个上传任务(一次请求上传一个文件)
private async void btnAddUpload_Click(object sender, RoutedEventArgs e)
{
// 上传服务的地址
Uri serverUri = new Uri("http://localhost:39629/UploadFile.aspx", UriKind.Absolute);
StorageFile sourceFile;
try
{
// 文件源
sourceFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/Logo.png", UriKind.Absolute));
}
catch (Exception ex)
{
lblMsg.Text += ex.ToString();
lblMsg.Text += Environment.NewLine;
return;
}
// 实例化 BackgroundUploader,并设置 http header
BackgroundUploader backgroundUploader = new BackgroundUploader();
backgroundUploader.SetRequestHeader("Filename", "Logo.png");
// 创建一个后台上传任务,此任务包含一个上传文件
UploadOperation upload = backgroundUploader.CreateUpload(serverUri, sourceFile);
// 以流的方式创建一个后台上传任务
// await backgroundUploader.CreateUploadFromStreamAsync(Uri uri, IInputStream sourceStream);
// 监视指定的后台上传任务
await HandleUploadAsync(upload, true);
}
// 新增一个上传任务(一次请求上传多个文件)
private async void btnAddMultiUpload_Click(object sender, RoutedEventArgs e)
{
// 上传服务的地址
Uri serverUri = new Uri("http://localhost:39629/UploadFile.aspx", UriKind.Absolute);
// 需要上传的文件源集合
List sourceFiles = new List();
for (int i = 0; i < 3; i++)
{
StorageFile sourceFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/Logo.png", UriKind.Absolute));
sourceFiles.Add(sourceFile);
}
// 构造需要上传 BackgroundTransferContentPart 集合
List contentParts = new List();
for (int i = 0; i < sourceFiles.Count; i++)
{
BackgroundTransferContentPart contentPart = new BackgroundTransferContentPart("File" + i, sourceFiles.Name);
contentPart.SetFile(sourceFiles);
contentParts.Add(contentPart);
}
// 创建一个后台上传任务,此任务包含多个上传文件
BackgroundUploader backgroundUploader = new BackgroundUploader();
UploadOperation upload = await backgroundUploader.CreateUploadAsync(serverUri, contentParts);
// 监视指定的后台上传任务
await HandleUploadAsync(upload, true);
}
///
/// 监视指定的后台上传任务
///
/// 后台上传任务
/// 是否是新增的任务
private async Task HandleUploadAsync(UploadOperation upload, bool isNew)
{
try
{
// 将 UploadOperation 附加到 TransferModel,以便上传进度可通知
TransferModel transfer = new TransferModel();
transfer.UploadOperation = upload;
transfer.Source = "多个文件";
transfer.Destination = upload.RequestedUri.ToString();
transfer.Progress = "0 / 0";
_transfers.Add(transfer);
lblMsg.Text += "Task Count: " + _transfers.Count.ToString();
lblMsg.Text += Environment.NewLine;
// 当上传进度发生变化时的回调函数
Progress progressCallback = new Progress(UploadProgress);
if (isNew)
await upload.StartAsync().AsTask(_cancelToken.Token, progressCallback); // 新增一个后台上传任务
else
await upload.AttachAsync().AsTask(_cancelToken.Token, progressCallback); // 监视已存在的后台上传任务
// 上传完成后获取服务端的响应信息
ResponseInformation response = upload.GetResponseInformation();
lblMsg.Text += "Completed: " + response.ActualUri + "-" + response.StatusCode.ToString();
lblMsg.Text += Environment.NewLine;
}
catch (TaskCanceledException) // 调用 CancellationTokenSource.Cancel() 后会抛出此异常
            {
lblMsg.Text += "Canceled: " + upload.Guid;
lblMsg.Text += Environment.NewLine;
}
catch (Exception ex)
{
// 将异常转换为 WebErrorStatus 枚举,如果获取到的是 WebErrorStatus.Unknown 则说明此次异常不是涉及 web 的异常
WebErrorStatus error = BackgroundTransferError.GetStatus(ex.HResult);
lblMsg.Text += ex.ToString();
lblMsg.Text += Environment.NewLine;
}
finally
{
_transfers.Remove(_transfers.First(p => p.UploadOperation == upload));
}
}
// 进度发生变化时,更新 TransferModel 的 Progress,以便通知
private void UploadProgress(UploadOperation upload)
{
TransferModel transfer = _transfers.First(p => p.UploadOperation == upload);
transfer.Progress = upload.Progress.BytesSent.ToString("#,0") + " / " + upload.Progress.TotalBytesToSend.ToString("#,0");
}
// 取消全部后台上传任务
private void btnCancel_Click(object sender, RoutedEventArgs e)
{
_cancelToken.Cancel();
_cancelToken.Dispose();
_cancelToken = new CancellationTokenSource();
}
}
}
  用于接收上传文件的服务
WebServer/UploadFile.aspx.cs



/*
* 用于接收上传文件的服务
*/
using System;
using System.IO;
namespace WebServer
{
public partial class UploadFile : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
try
{
if (Request.Headers["Filename"] != null)
{
// 接收单个文件,并保存
string fileName = Request.Headers["Filename"];
string saveLocation = Server.MapPath("UploadFiles") + "\\" + fileName.Insert(fileName.IndexOf("."), "_" + Guid.NewGuid().ToString());
using (System.IO.FileStream fs = new System.IO.FileStream(saveLocation, FileMode.Create))
{
Request.InputStream.CopyTo(fs);
}
}
else
{
// 接收多个文件,并保存
for (int i = 0; i < Request.Files.Count; i++)
{
var file = Request.Files;
if (file.ContentLength > 0)
{
string fileName = System.IO.Path.GetFileName(file.FileName);
string saveLocation = Server.MapPath("UploadFiles") + "\\" + fileName.Insert(fileName.IndexOf("."), "_" + Guid.NewGuid().ToString());
file.SaveAs(saveLocation);
}
}
}
}
catch (Exception ex)
{
Trace.Write(ex.Message);
Response.StatusCode = 500;
Response.StatusDescription = ex.Message;
Response.End();
}
}
}
}
  
OK
[源码下载]

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-69322-1-1.html 上篇帖子: 重新想象 Windows 8 Store Apps (29) 下篇帖子: Windows 8 Metro 关于StreamSocket与原异步Socket
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表