[源码下载]

背水一战 Windows 10 (120) - 后台任务: 后台上传任务

作者:webabcd

介绍
背水一战 Windows 10 之 后台任务

  • 后台上传任务

示例
演示 uwp 的后台上传任务
BackgroundTask/TransferModel.cs

/*
* 扩展了 DownloadOperation 和 UploadOperation,用于 MVVM 绑定数据
*/ using System;
using System.ComponentModel;
using Windows.Networking.BackgroundTransfer; namespace Windows10.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));
}
}
}
}

BackgroundTask/TransferUpload.xaml

<Page
x:Class="Windows10.BackgroundTask.TransferUpload"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Windows10.BackgroundTask"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"> <Grid Background="Transparent">
<StackPanel Margin="10 0 10 10"> <ScrollViewer Name="scrollViewer" Height="100" Margin="5">
<TextBlock Name="lblMsg" TextWrapping="Wrap" />
</ScrollViewer> <Button Name="btnAddUpload" Content="新增一个上传任务(一次请求上传一个文件)" Margin="5" Click="btnAddUpload_Click" />
<Button Name="btnAddMultiUpload" Content="新增一个上传任务(一次请求上传多个文件)" Margin="5" Click="btnAddMultiUpload_Click" />
<Button Name="btnCancel" Content="取消所有上传任务" Margin="5" Click="btnCancel_Click" /> <ListView Name="listView" Height="286" Padding="5">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0 5" Background="Blue">
<TextBlock Text="{Binding Source}" Margin="5" />
<TextBlock Text="{Binding Destination}" Margin="5" />
<TextBlock Text="{Binding Progress}" Margin="5" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView> </StackPanel>
</Grid>
</Page>

BackgroundTask/TransferUpload.xaml.cs

/*
* 演示 uwp 的后台上传任务
*
* BackgroundUploader - 后台上传任务管理器
* CreateUpload(Uri uri, IStorageFile sourceFile) - 创建一个上传任务,返回 UploadOperation 对象
* CreateUploadFromStreamAsync(Uri uri, IInputStream sourceStream) - 以流的方式创建一个上传任务
* CreateUploadAsync(Uri uri, IEnumerable<BackgroundTransferContentPart> parts) - 创建一个包含多个上传文件的上传任务
* SetRequestHeader(string headerName, string headerValue) - 设置 http 请求头
* Method - 用于上传的 http method(默认 post)
* static GetCurrentUploadsAsync() - 获取当前 app 的未与组关联的所有上传任务
* CostPolicy - 上传的成本策略,BackgroundTransferCostPolicy 枚举
* Default - 不允许在高成本(比如 4G)网络上传输
* UnrestrictedOnly - 允许在高成本(比如 4G)网络上传输
* Always - 无论如何均可传输,即使在漫游时
* ServerCredential - 与服务端通信时的凭据
* ProxyCredential - 使用代理时的身份凭据
* SuccessToastNotification, SuccessTileNotification, FailureToastNotification, FailureTileNotification - 上传任务成功或失败后的 toast 或 tile 通知
* static GetCurrentUploadsForTransferGroupAsync(BackgroundTransferGroup group) - 获取指定组的所有上传任务
* TransferGroup - 设置或获取分组对象(BackgroundTransferGroup 类型)
* BackgroundUploader(BackgroundTransferCompletionGroup completionGroup) - 通过指定的 BackgroundTransferCompletionGroup 对象实例化 BackgroundUploader 对象
* CompletionGroup - 获取关联的 BackgroundTransferCompletionGroup 对象
*
* UploadOperation - 上传任务对象
* Guid - 获取此上传任务的标识
* CostPolicy - 上传的成本策略,BackgroundTransferCostPolicy 枚举
* RequestedUri - 上传任务所请求的服务端地址
* SourceFile - 需要上传的文件,如果是一次上传多个文件则此属性为 null
* Method - 获取用于上传的 http method(get, post 之类的)
* GetResponseInformation() - 上传完成后获取到的服务端响应信息,返回 ResponseInformation 对象
* ActualUri - 上传服务的真实 URI
* Headers - 服务端响应的 HTTP 头
* StatusCode - 服务端响应的状态码
* StartAsync() - 新增一个上传任务,返回 IAsyncOperationWithProgress<UploadOperation, UploadOperation> 对象
* AttachAsync() - 监视已存在的上传任务,返回 IAsyncOperationWithProgress<UploadOperation, UploadOperation> 对象
* Progress - 获取上传进度,返回 BackgroundUploadProgress 对象
* Priority - 上传的优先级,BackgroundTransferPriority 枚举
* Default 或 High
* TransferGroup - 获取此上传任务的分组对象(BackgroundTransferGroup 类型)
*
* BackgroundUploadProgress - 后台上传任务的上传进度对象
* BytesSent - 已上传的字节数
* TotalBytesToSend - 总共需要上传的字节数
* BytesReceived - 已下载的字节数
* TotalBytesToReceive - 总共需要下载的字节数,未知则为 0
* Status - 上传状态,BackgroundTransferStatus 枚举
* Idle, Running, PausedByApplication, PausedCostedNetwork, PausedNoNetwork, Completed, Canceled, Error
* HasResponseChanged - 服务端响应了则为 true
* HasRestarted - 当上传连接断掉后,系统会重新上传,此种情况则为 true
*
* BackgroundTransferGroup - 后台上传任务的分组对象
* static BackgroundTransferGroup CreateGroup(string name) - 创建指定分组标识的 BackgroundTransferGroup 对象
* Name - 分组标识(只读)
* TransferBehavior - 组内上传任务的执行方式,BackgroundTransferBehavior 枚举
* Parallel - 并行
* Serialized - 串行
*
* BackgroundTransferCompletionGroup - 分组对象(用于实现“组任务全部完成后触发后台任务”)
* Enable() - 启用“组任务全部完成后触发后台任务”的功能
* IsEnabled - 是否启用了“组任务全部完成后触发后台任务”的功能(只读)
* Trigger - “组任务全部完成后触发后台任务”的触发器
*
* BackgroundTransferContentPart - 当一次上传多个文件时,将每个需要上传的文件构造成一个 BackgroundTransferContentPart 对象
* BackgroundTransferContentPart(string name, string fileName) - 通过一个标识和文件名称实例化 BackgroundTransferContentPart 对象
* SetFile(IStorageFile value) - 指定需要上传的文件
*
*
* 注:关于上传任务的“任务分组,并行或串行执行,组完成后通知”和“任务分组,组完成后触发后台任务”的实现方式与下载任务是一样的,请参见下载任务的相关演示示例(TransferGroup.xaml.cs 和 TransferBackground.xaml.cs)
*/ using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Windows.Data.Xml.Dom;
using Windows.Networking.BackgroundTransfer;
using Windows.Storage;
using Windows.UI.Notifications;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.Web; namespace Windows10.BackgroundTask
{
public sealed partial class TransferUpload : Page
{
// 上传任务的集合
private ObservableCollection<TransferModel> _transfers = new ObservableCollection<TransferModel>(); // 所有上传任务的关联的 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<UploadOperation> uploads = null;
try
{
// 获取所有后台上传任务
uploads = await BackgroundUploader.GetCurrentUploadsAsync();
}
catch (Exception ex)
{
WriteLine(ex.ToString());
return;
} if (uploads.Count > )
{
List<Task> tasks = new List<Task>();
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:44914/api/Upload", UriKind.Absolute); StorageFile sourceFile;
try
{
// 需要上传的文件
sourceFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/hololens.jpg", UriKind.Absolute));
}
catch (Exception ex)
{
WriteLine(ex.ToString());
return;
} // 实例化 BackgroundUploader,并设置 http header
BackgroundUploader backgroundUploader = new BackgroundUploader();
backgroundUploader.SetRequestHeader("Filename", "hololens.jpg"); // 任务成功后弹出指定的 toast 通知(类似的还有 SuccessTileNotification, FailureToastNotification, FailureTileNotification)
backgroundUploader.SuccessToastNotification = GetToastNotification(); // 创建一个后台上传任务,此任务包含一个上传文件
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:44914/api/Upload", UriKind.Absolute); // 需要上传的文件源集合
List<StorageFile> sourceFiles = new List<StorageFile>();
for (int i = ; i < ; i++)
{
StorageFile sourceFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/hololens.jpg", UriKind.Absolute));
sourceFiles.Add(sourceFile);
} // 构造需要上传 BackgroundTransferContentPart 集合
List<BackgroundTransferContentPart> contentParts = new List<BackgroundTransferContentPart>();
for (int i = ; i < sourceFiles.Count; i++)
{
BackgroundTransferContentPart contentPart = new BackgroundTransferContentPart("File" + i, sourceFiles[i].Name);
contentPart.SetFile(sourceFiles[i]);
contentParts.Add(contentPart);
} BackgroundUploader backgroundUploader = new BackgroundUploader(); // 任务成功后弹出指定的 toast 通知(类似的还有 SuccessTileNotification, FailureToastNotification, FailureTileNotification)
backgroundUploader.SuccessToastNotification = GetToastNotification(); // 创建一个后台上传任务,此任务包含多个上传文件
UploadOperation upload = await backgroundUploader.CreateUploadAsync(serverUri, contentParts); // 处理并监视指定的后台上传任务
await HandleUploadAsync(upload, true);
} /// <summary>
/// 处理并监视指定的后台上传任务
/// </summary>
/// <param name="upload">后台上传任务</param>
/// <param name="isNew">是否是新增的任务</param>
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 = upload.Progress.Status.ToString() + "0 / 0"; _transfers.Add(transfer); WriteLine("Task Count: " + _transfers.Count.ToString()); // 当上传进度发生变化时的回调函数
Progress<UploadOperation> progressCallback = new Progress<UploadOperation>(UploadProgress); if (isNew)
await upload.StartAsync().AsTask(_cancelToken.Token, progressCallback); // 启动一个后台上传任务
else
await upload.AttachAsync().AsTask(_cancelToken.Token, progressCallback); // 监视已存在的后台上传任务 // 上传完成后获取服务端的响应信息
ResponseInformation response = upload.GetResponseInformation();
WriteLine("Completed: " + response.ActualUri + ", HttpStatusCode: " + response.StatusCode.ToString());
}
catch (TaskCanceledException) // 调用 CancellationTokenSource.Cancel() 后会抛出此异常
{
WriteLine("Canceled: " + upload.Guid);
}
catch (Exception ex)
{
// 将异常转换为 WebErrorStatus 枚举,如果获取到的是 WebErrorStatus.Unknown 则说明此次异常不是涉及 web 的异常
WebErrorStatus error = BackgroundTransferError.GetStatus(ex.HResult); WriteLine(ex.ToString());
}
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.Status.ToString() + ": " + 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();
} // 向 lblMsg 中追加一行文本
private void WriteLine(string message)
{
lblMsg.Text += message;
lblMsg.Text += Environment.NewLine; scrollViewer.ChangeView(, scrollViewer.ScrollableHeight, 1f);
} // 构造指定的 toast 通知
private ToastNotification GetToastNotification()
{
string toastXml = $@"
<toast activationType='foreground'>
<visual>
<binding template='ToastGeneric'>
<text>toast - title</text>
<text>上传任务成功完成</text>
</binding>
</visual>
</toast>"; XmlDocument toastDoc = new XmlDocument();
toastDoc.LoadXml(toastXml); return new ToastNotification(toastDoc);
}
}
}

OK
[源码下载]

背水一战 Windows 10 (120) - 后台任务: 后台上传任务的更多相关文章

  1. 背水一战 Windows 10 (117) - 后台任务: 后台下载任务

    [源码下载] 背水一战 Windows 10 (117) - 后台任务: 后台下载任务 作者:webabcd 介绍背水一战 Windows 10 之 后台任务 后台下载任务 示例演示 uwp 的后台下 ...

  2. 背水一战 Windows 10 (119) - 后台任务: 后台下载任务(任务分组,组完成后触发后台任务)

    [源码下载] 背水一战 Windows 10 (119) - 后台任务: 后台下载任务(任务分组,组完成后触发后台任务) 作者:webabcd 介绍背水一战 Windows 10 之 后台任务 后台下 ...

  3. 背水一战 Windows 10 (118) - 后台任务: 后台下载任务(任务分组,并行或串行执行,组完成后通知)

    [源码下载] 背水一战 Windows 10 (118) - 后台任务: 后台下载任务(任务分组,并行或串行执行,组完成后通知) 作者:webabcd 介绍背水一战 Windows 10 之 后台任务 ...

  4. 背水一战 Windows 10 (121) - 后台任务: 推送通知

    [源码下载] 背水一战 Windows 10 (121) - 后台任务: 推送通知 作者:webabcd 介绍背水一战 Windows 10 之 后台任务 推送通知 示例演示如何接收推送通知/WebA ...

  5. 背水一战 Windows 10 (114) - 后台任务: 后台任务的 Demo(与 app 不同进程), 后台任务的 Demo(与 app 相同进程)

    [源码下载] 背水一战 Windows 10 (114) - 后台任务: 后台任务的 Demo(与 app 不同进程), 后台任务的 Demo(与 app 相同进程) 作者:webabcd 介绍背水一 ...

  6. 背水一战 Windows 10 (115) - 后台任务: 通过 toast 激活后台任务, 定时激活后台任务

    [源码下载] 背水一战 Windows 10 (115) - 后台任务: 通过 toast 激活后台任务, 定时激活后台任务 作者:webabcd 介绍背水一战 Windows 10 之 后台任务 通 ...

  7. 背水一战 Windows 10 (116) - 后台任务: 前台程序激活后台任务

    [源码下载] 背水一战 Windows 10 (116) - 后台任务: 前台程序激活后台任务 作者:webabcd 介绍背水一战 Windows 10 之 后台任务 前台程序激活后台任务 示例演示后 ...

  8. 背水一战 Windows 10 (36) - 控件(弹出类): ToolTip, Popup, PopupMenu

    [源码下载] 背水一战 Windows 10 (36) - 控件(弹出类): ToolTip, Popup, PopupMenu 作者:webabcd 介绍背水一战 Windows 10 之 控件(弹 ...

  9. 背水一战 Windows 10 (39) - 控件(布局类): VariableSizedWrapGrid, Border, Viewbox, SplitView

    [源码下载] 背水一战 Windows 10 (39) - 控件(布局类): VariableSizedWrapGrid, Border, Viewbox, SplitView 作者:webabcd ...

随机推荐

  1. jq实现前端文件上传

    FormData FormData是XMLHttpRequest Level 2 新增的一个接口. 使用FormData可以实现各种文件上传. 使用 // 创建FormData的实例 var form ...

  2. xmltodict 模块

    pip install xmltodict xmltodict.parse() 方法可以将xml数据转为python中的dict字典数据 xmltodict.unparse() 将字典转换为xml数据 ...

  3. 过滤器(Filter)与拦截器(Interceptor )区别

    目录 过滤器(Filter) 拦截器(Interceptor) 拦截器(Interceptor)和过滤器(Filter)的区别 拦截器(Interceptor)和过滤器(Filter)的执行顺序 拦截 ...

  4. eclipse Filter web.xml 问题解决 异步请求@WebServlet

    <filter> <filter-name>AsynServlete</filter-name> <filter-class>com.kad.app.a ...

  5. 使用Typescript实现依赖注入(DI)

    前言DI总是和ico相辅相成的,如果想对DI有更多的了解,可以移步我的另一篇文章 依赖注入(DI)和控制反转(IOC),再次我就不多做赘述了. 前几天看见一道面试题,今天借这个话题想跟大家分享一下: ...

  6. 用DOM方式解析XML

    一.用DOM方式解析XML 此例子节点结构如下: 1.获取book节点属性 (1).如果不知道节点的属性,通过 NamedNodeMap attrs = book.getAttributes(); 来 ...

  7. SqlServer2012,设置指定数据库对指定用户开放权限

    REVOKE VIEW ANY DATABASE TO [public] --这个是取消数据库公开的权限,也就是除了sa角色外任何人都不能查看数据库 -- 现在用sa用户登录Use [要开放权限的数据 ...

  8. Asp.net Zero 应用实战-官方示例PhoneBook学习1

    适用Zero版本:ASP.NET Core & Angular 2+ (aspnet-zero-core-3.1.0). 该版本官方有两个solution文件夹:Angular(前端) 和 a ...

  9. UVA 2290 Transmitters

    题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_ ...

  10. 20155312 张竞予 Exp6 信息搜集与漏洞扫描

    Exp6 信息搜集与漏洞扫描 目录 基础问题回答 (1)哪些组织负责DNS,IP的管理. (2)什么是3R信息. (3)评价下扫描结果的准确性. 实验总结与体会 实践过程记录 (1)各种搜索技巧的应用 ...