与众不同 windows phone (13) - Background Task(后台任务)之后台文件传输(上传和下载)
原文:与众不同 windows phone (13) - Background Task(后台任务)之后台文件传输(上传和下载)
作者:webabcd
介绍
与众不同 windows phone 7.5 (sdk 7.1) 之后台任务
- 后台文件传输(下载)
- 后台文件传输(上传)
示例
1、演示如何实现后台文件传输(下载)
BackgroundTransferDownload.xaml
<phone:PhoneApplicationPage
x:Class="Demo.BackgroundTask.BackgroundTransferDownload"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"
shell:SystemTray.IsVisible="True"> <Grid x:Name="LayoutRoot" Background="Transparent">
<StackPanel Orientation="Vertical"> <Button x:Name="btnDownloadSilverlightDemo" Content="下载 Silverlight Demo 压缩包" Click="btnDownloadSilverlightDemo_Click" />
<Button x:Name="btnDownloadXNADemo" Content="下载 XNA Demo 压缩包" Click="btnDownloadXNADemo_Click" />
<Button x:Name="btnDownloadWindowsPhoneDemo" Content="下载 WindowsPhone Demo 压缩包" Click="btnDownloadWindowsPhoneDemo_Click" /> <TextBlock Text="下载任务列表:" Margin="0 15 0 0" />
<ListBox Name="listBox">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="0 15" Width="480">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="8*"/>
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions> <Grid>
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<TextBlock Text="文件名: "/>
<TextBlock Text="{Binding Tag}"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="下载状态: "/>
<TextBlock Text="{Binding TransferStatus}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="已接收字节数: "/>
<TextBlock Text="{Binding BytesReceived}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="总共字节数: "/>
<TextBlock Text="{Binding TotalBytesToReceive}" />
</StackPanel>
</StackPanel> </Grid>
<Grid Grid.Column="1">
<Button x:Name="btnCancel" Tag="{Binding RequestId}" Click="btnCancel_Click" Content="删除任务"></Button>
</Grid>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox> </StackPanel>
</Grid> </phone:PhoneApplicationPage>
BackgroundTransferDownload.xaml.cs
/*
* 演示如何实现后台文件传输(下载)
*
*
* BackgroundTransferRequest - 后台文件传输请求
* BackgroundTransferRequest(Uri) - 构造函数。参数解释:下载时其为需要下载的文件的远程地址;上传时其为接收文件的远程服务地址
* RequestId - 后台文件传输请求的唯一 ID,只读
* RequestUri - 请求的地址,只读。其需要在构造函数中设置
* Method - 请求的 http 方法,GET - 下载;POST - 上传
* Headers - 请求的 http 头,有一些头信息不能自定义,如 Range 等
* StatusCode - http 请求回应的状态码
* Tag - 自定义此对象的关联信息,即上下文数据
* TransferPreferences - 传输的启动条件(Microsoft.Phone.BackgroundTransfer.TransferPreferences 枚举)
* None - 仅在外部电源 + WiFi 环境下允许传输
* AllowCellular - 允许在手机网络环境下传输
* AllowBattery - 允许在电池做电源的环境下传输
* AllowCellularAndBattery - 允许在电池电源 + 手机网络的环境下传输
* TransferError - 错误信息
* TransferStatus - 传输状态(Microsoft.Phone.BackgroundTransfer.TransferStatus 枚举)
* None - 传输任务尚未加入到传输队列
* Waiting - 在传输队列,等待传输
* Transferring - 传输中
* Paused - 暂停
* Completed - 传输任务已完成,如果传输成功则 TransferError 为 null
* WaitingForWiFi - WiFi 网络
* WaitingForExternalPower - 需要接上外接电源
* WaitingForExternalPowerDueToBatterySaverMode - 需要接上外接电源,或者禁用节电模式
* WaitingForNonVoiceBlockingNetwork - 不能使用无法和语音并发的网络(如 2G、EDGE 和标准 GPRS)
* DownloadLocation - 下载到的目标位置
* UploadLocation - 需要上传的文件的地址
* BytesReceived - 文件已下载的字节数
* BytesSent - 文件已上传的字节数
* TotalBytesToReceive - 需要下载的文件的总字节数(-1 则文件大小未知)
* TotalBytesToSend - 需要上传的文件的总字节数(-1 则文件大小未知)
*
* TransferProgressChanged - 传输进度改变时所触发的事件
* TransferStatusChanged - 属性 TransferStatus 发生改变时所触发的事件
*
*
* BackgroundTransferService - 对后台文件传输请求的管理
* Add() - 添加一个 BackgroundTransferRequest
* Find() - 通过 RequestId 查找指定的 BackgroundTransferRequest
* Remove - 通过 RequestId 删除指定的 BackgroundTransferRequest
*
*
* 注意:
* 后台文件传输既支持 http 又支持 https
* 传输的文件必须在 /shared/transfers 目录下
* 上传文件最大 5 MB,手机网络下载文件最大 20 MB,WiFi+电池电源下载文件最大 100 MB,WiFi+外接电源下载文件则允许大于 100 MB
* 下载文件超过 5 MB 时,系统会向服务端发 Range 头分段下载(不会多线程下载,但是会断点续传)
* 每个应用程序的传输任务队列,最大支持 5 个任务,设备支持 500 个任务
* 设备上最大并发传输数为 2 个
*/ using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls; using Microsoft.Phone.BackgroundTransfer;
using System.IO.IsolatedStorage; namespace Demo.BackgroundTask
{
public partial class BackgroundTransferDownload : PhoneApplicationPage
{
public BackgroundTransferDownload()
{
InitializeComponent();
} protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
// 为每个 BackgroundTransferRequest 注册相关事件
foreach (var transfer in BackgroundTransferService.Requests)
{
transfer.TransferStatusChanged += new EventHandler<BackgroundTransferEventArgs>(transfer_TransferStatusChanged);
transfer.TransferProgressChanged += new EventHandler<BackgroundTransferEventArgs>(transfer_TransferProgressChanged);
} UpdateUI();
} private void ProcessTransfer(BackgroundTransferRequest transfer)
{
switch (transfer.TransferStatus)
{
case TransferStatus.Completed:
// 200 - 下载完成;206 - 分块下载完成
if (transfer.StatusCode == || transfer.StatusCode == )
{
// 下载完成后不会自动从队列中删除,需要手动删除
RemoveTransferRequest(transfer.RequestId); // 将下载完成后的文件移动到独立存储的根目录下
using (IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication())
{
string filename = transfer.Tag;
if (isoStore.FileExists(filename))
{
isoStore.DeleteFile(filename);
}
isoStore.MoveFile(transfer.DownloadLocation.OriginalString, filename);
}
}
else
{
// 如果回应的不是 200 或 206 则意味着出现了问题
// 将任务其移出队列
RemoveTransferRequest(transfer.RequestId); // 发生了异常,做一些相关处理
if (transfer.TransferError != null)
{
MessageBox.Show(transfer.TransferError.ToString());
}
}
break; // 注:以下 4 个状态最好做一下判断和处理,然后呈现给用户
case TransferStatus.WaitingForExternalPower:
break;
case TransferStatus.WaitingForExternalPowerDueToBatterySaverMode:
break;
case TransferStatus.WaitingForNonVoiceBlockingNetwork:
break;
case TransferStatus.WaitingForWiFi:
break;
}
} void transfer_TransferStatusChanged(object sender, BackgroundTransferEventArgs e)
{
ProcessTransfer(e.Request); UpdateUI();
} void transfer_TransferProgressChanged(object sender, BackgroundTransferEventArgs e)
{
UpdateUI();
} private void btnCancel_Click(object sender, EventArgs e)
{
string transferId = ((Button)sender).Tag as string;
RemoveTransferRequest(transferId); UpdateUI();
} // 从 BackgroundTransferService 中删除指定的传输请求
private void RemoveTransferRequest(string transferId)
{
BackgroundTransferRequest transfer = BackgroundTransferService.Find(transferId); try
{
if (transfer != null)
BackgroundTransferService.Remove(transfer);
}
catch (Exception ex)
{
MessageBox.Show("RemoveTransferRequest: " + ex.ToString());
}
} private void UpdateUI()
{
// 更新 UI
listBox.ItemsSource = BackgroundTransferService.Requests;
} private void btnDownloadSilverlightDemo_Click(object sender, RoutedEventArgs e)
{
// 如果 url 中有特殊字符,如汉字等,建议使用 Uri.EscapeUriString 编码
AddBackgroundTransfer("Silverlight.rar", new Uri("http://files.cnblogs.com/webabcd/Silverlight.rar", UriKind.Absolute)); UpdateUI();
} private void btnDownloadXNADemo_Click(object sender, RoutedEventArgs e)
{
AddBackgroundTransfer("XNA.rar", new Uri("http://files.cnblogs.com/webabcd/XNA.rar", UriKind.Absolute)); UpdateUI();
} private void btnDownloadWindowsPhoneDemo_Click(object sender, RoutedEventArgs e)
{
AddBackgroundTransfer("WindowsPhone.rar", new Uri("http://files.cnblogs.com/webabcd/WindowsPhone.rar", UriKind.Absolute)); UpdateUI();
} /// <summary>
/// 添加后台传输任务到队列
/// </summary>
/// <param name="fileName">需要在本地保存的文件名</param>
/// <param name="fileUri">需要下载的文件的远程地址</param>
private void AddBackgroundTransfer(string fileName, Uri fileUri)
{
// 做一下相关判断
if (BackgroundTransferService.Requests.Count() >= )
{
MessageBox.Show("每个应用程序的后台传输队列最多只能有 5 个任务");
return;
}
if (BackgroundTransferService.Requests.Any(p => p.RequestUri == fileUri))
{
MessageBox.Show("任务已在队列中");
return;
} BackgroundTransferRequest transferRequest = new BackgroundTransferRequest(fileUri);
transferRequest.Method = "GET"; // 下载
transferRequest.TransferPreferences = TransferPreferences.None; // 仅在外部电源 + WiFi 环境下允许下载 transferRequest.TransferStatusChanged += new EventHandler<BackgroundTransferEventArgs>(transfer_TransferStatusChanged);
transferRequest.TransferProgressChanged += new EventHandler<BackgroundTransferEventArgs>(transfer_TransferProgressChanged); transferRequest.Tag = fileName; // 给 TransferRequest 赋值一个上下文数据
transferRequest.DownloadLocation = new Uri("shared/transfers/" + fileName, UriKind.Relative); try
{
BackgroundTransferService.Add(transferRequest);
}
catch (Exception ex)
{
MessageBox.Show("AddBackgroundTransfer: " + ex.ToString());
}
}
}
}
2、演示如何实现后台文件传输(上传)
BackgroundTransferUpload.xaml
<phone:PhoneApplicationPage
x:Class="Demo.BackgroundTask.BackgroundTransferUpload"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"
shell:SystemTray.IsVisible="True"> <Grid x:Name="LayoutRoot" Background="Transparent">
<StackPanel Orientation="Vertical"> <Button x:Name="btnUpload" Content="上传 Demo.mp4 文件到服务端" Click="btnUpload_Click" /> </StackPanel>
</Grid> </phone:PhoneApplicationPage>
BackgroundTransferUpload.xaml.cs
/*
* 演示如何实现后台文件传输(上传)
*
* BackgroundTransferRequest、BackgroundTransferService 及相关注意事项详见:BackgroundTask/BackgroundTransferDownload.xaml.cs
*/ using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls; using Microsoft.Phone.BackgroundTransfer;
using System.IO.IsolatedStorage;
using System.Windows.Resources;
using System.IO; namespace Demo.BackgroundTask
{
public partial class BackgroundTransferUpload : PhoneApplicationPage
{
public BackgroundTransferUpload()
{
InitializeComponent();
} protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
// 为每个 BackgroundTransferRequest 注册相关事件
foreach (var transfer in BackgroundTransferService.Requests)
{
transfer.TransferStatusChanged += new EventHandler<BackgroundTransferEventArgs>(transfer_TransferStatusChanged);
transfer.TransferProgressChanged += new EventHandler<BackgroundTransferEventArgs>(transfer_TransferProgressChanged);
}
} private void ProcessTransfer(BackgroundTransferRequest transfer)
{
switch (transfer.TransferStatus)
{
case TransferStatus.Completed:
// 200 代表上传成功
if (transfer.StatusCode == )
{
MessageBox.Show("上传成功");
}
else
{
// 发生了异常,做一些相关处理
if (transfer.TransferError != null)
{
MessageBox.Show(transfer.TransferError.ToString());
}
}
RemoveTransferRequest(transfer.RequestId);
break; // 注:以下 4 个状态最好做一下判断和处理,然后呈现给用户
case TransferStatus.WaitingForExternalPower:
break;
case TransferStatus.WaitingForExternalPowerDueToBatterySaverMode:
break;
case TransferStatus.WaitingForNonVoiceBlockingNetwork:
break;
case TransferStatus.WaitingForWiFi:
break;
}
} void transfer_TransferStatusChanged(object sender, BackgroundTransferEventArgs e)
{
ProcessTransfer(e.Request);
} void transfer_TransferProgressChanged(object sender, BackgroundTransferEventArgs e)
{
// 上传进度发生改变
} private void btnCancel_Click(object sender, EventArgs e)
{
string transferId = ((Button)sender).Tag as string;
RemoveTransferRequest(transferId);
} // 从 BackgroundTransferService 中删除指定的传输请求
private void RemoveTransferRequest(string transferId)
{
BackgroundTransferRequest transfer = BackgroundTransferService.Find(transferId); try
{
if (transfer != null)
BackgroundTransferService.Remove(transfer);
}
catch (Exception ex)
{
MessageBox.Show("RemoveTransferRequest: " + ex.ToString());
}
} private void btnUpload_Click(object sender, RoutedEventArgs e)
{
// 将 Demo.mp4 文件从程序包复制到独立存储的 shared/transfers 目录,以备上传
StreamResourceInfo sr = Application.GetResourceStream(new Uri("Assets/Demo.mp4", UriKind.Relative));
using (BinaryReader br = new BinaryReader(sr.Stream))
{
byte[] data = br.ReadBytes((int)sr.Stream.Length); IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication();
using (var isfs = new IsolatedStorageFileStream(@"shared/transfers/Demo.mp4", FileMode.Create, isf))
{
using (var bw = new BinaryWriter(isfs))
{
bw.Write(data);
}
}
} AddBackgroundTransfer("Demo.mp4", new Uri(@"shared/transfers/Demo.mp4", UriKind.Relative));
} /// <summary>
/// 添加后台传输任务到队列
/// </summary>
/// <param name="fileName">需要在服务端保存的文件名</param>
/// <param name="fileUri">需要上传的文件的本地地址</param>
private void AddBackgroundTransfer(string fileName, Uri fileUri)
{
BackgroundTransferRequest transferRequest = new BackgroundTransferRequest(new Uri("http://localhost:15482/UploadFile.aspx?fileName=" + fileName, UriKind.Absolute));
transferRequest.Method = "POST"; // 上传
transferRequest.TransferPreferences = TransferPreferences.None; // 仅在外部电源 + WiFi 环境下允许上传 transferRequest.TransferStatusChanged += new EventHandler<BackgroundTransferEventArgs>(transfer_TransferStatusChanged);
transferRequest.TransferProgressChanged += new EventHandler<BackgroundTransferEventArgs>(transfer_TransferProgressChanged); transferRequest.UploadLocation = fileUri; try
{
BackgroundTransferService.Add(transferRequest);
}
catch (Exception ex)
{
MessageBox.Show("AddBackgroundTransfer: " + ex.ToString());
}
}
}
}
UploadFile.aspx.cs(用于保存上传文件的服务端代码)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.IO; namespace Web
{
public partial class UploadFile : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (Request.TotalBytes > )
{
// 保存上传过来的文件
byte[] data = Request.BinaryRead(Request.TotalBytes);
File.WriteAllBytes(@"C:\" + Request.QueryString["fileName"], data);
}
}
}
}
OK
[源码下载]
与众不同 windows phone (13) - Background Task(后台任务)之后台文件传输(上传和下载)的更多相关文章
- 与众不同 windows phone (12) - Background Task(后台任务)之 PeriodicTask(周期任务)和 ResourceIntensiveTask(资源密集型任务)
原文:与众不同 windows phone (12) - Background Task(后台任务)之 PeriodicTask(周期任务)和 ResourceIntensiveTask(资源密集型任 ...
- 与众不同 windows phone (11) - Background Task(后台任务)之警报(Alarm)和提醒(Reminder)
原文:与众不同 windows phone (11) - Background Task(后台任务)之警报(Alarm)和提醒(Reminder) [索引页][源码下载] 与众不同 windows p ...
- Xshell在Windows和Linux间文件的上传和下载
本文通过lrzsz来实现Windows和Linux间文件间的文件传输. lrzsz使用 XMODEM.YMODEM 和 ZMODEM 文件传输协议来实现文件的上传和下载.相比 FTP 或者 WinSC ...
- 记crt 在windows与linux服务器之间利用ftp进行文件的上传下载
我们首先来熟悉一些相关的命令以及操作: ls #展示linux服务器当前工作目录[你连接sftp时所处的目录]下的所有文件以及文件夹 lcd F:\niki #绑定你在windo ...
- windows下实现linux的远程访问以及linux上文件的上传和下载
在网络性能.安全性.可管理性上,Linux有着其他系统无法比拟的强大优势,而服务器对这些方面要求特别高,因此Linux常常被用来做服务器使用.而当我们需要维护linux服务器的时候,就需要远程访问li ...
- windows下定时利用bat脚本实现ftp上传和下载
前言: 工作中可能会遇到以下情况,利用windows作为中转,来实现两台linux服务器的文件传输. 实现步骤: 1.FTP上传和下载的bat脚本. 脚本分为两部分:可执行bat脚本和ftp命令文件: ...
- Git Gui for Windows的建库、克隆(clone)、上传(push)、下载(pull)、合并(转)
Git Gui for Windows的建库.克隆(clone).上传(push).下载(pull).合并(转) from:http://hi.baidu.com/mvp_xuan/blog/item ...
- Windows到Linux的文件上传、下载
1.使用我们常用的Xshell登录工具,新建立一个远程会话,填写ip地址及用户名密码后,选择最下面的ZMODEM,填写下载的路径.加载的路径:2个路径可以一样也可以不一样: 2.在Linux主机上,安 ...
- 在windows和linux之间用SecureCRT来上传和下载文件
SecureCRT可以使用linux下的zmodem协议来快速的传送文件,使用非常方便.具体步骤:一.在使用SecureCRT上传下载之前需要给服务器安装lrzsz:A:CentOS中使用yum安装即 ...
随机推荐
- 怎样删除在Github中创建的项目
像我这种刚開始学习的人总会不可避免的创建了一些測试性的项目.随后自然就是要删除了.那么该怎样删除呢? 你此刻可能处于这个界面: 也可能处于这个界面: 假设是第一个界面直接点击右側的"Sett ...
- 使用ffmpeg将BMP图片编码为x264视频文件,将H264视频保存为BMP图片,yuv视频文件保存为图片的代码
ffmpeg开源库,实现将bmp格式的图片编码成x264文件,并将编码好的H264文件解码保存为BMP文件. 实现将视频文件yuv格式保存的图片格式的測试,图像格式png,jpg, gif等等測试均O ...
- android软键盘弹出隐藏的监听
通过网上搜索关于软键盘的隐藏弹出的监听,有几种方式,其中最有效的方式是在View的Onlayout()里面做文章 具体代码: 将布局视图自定义,重写onlayout()方法,然后在主Activity里 ...
- 2008r2 显示桌面图标
- 第1章 Lua基础
1.1 全局变量 全局变量不需要声明,给一个变量赋值后即创建了这个全局变量,访问一个没有初始化的全局变量也不会出错,只不过得到的结果是:nil. 如果你想删除一个全局变量,只需要将变量负值为 nil ...
- linux指令(目录类操作指令)
pwd 显示当前所在的工作目录 cd 目标目录 例如cd /boot/grub 从当前目录切换到某个目录 cd 切换到根目录 cd.. 切换到当前目录的上层目录 ls 显示当前目录下的内容 ...
- Robot Framework与Web界面自动化测试学习笔记:利用xpath定位元素
在rf中,利用selinum2的关键字进行用例编写时,很多关键字的参数是html元素的定位标识. 最简单的方式,是通过id 或name来描述元素定位信息,如 click button id=l ...
- 一道经典的C++结构体的题目
题目描述: 有10个学生,每个学生的数据包括学号.姓名.英语.数学.物理三门课的成绩,从键盘输入10个学生数据,要求打印出3门课程的总平均成绩,以及最高分的学生的数据(包括学号,姓名,3门课的平均成绩 ...
- Android-onInterceptTouchEvent()和onTouchEvent()总结
老实说,这两个小东东实在是太麻烦了,很不好懂,我自己那api文档都头晕,在网上找到很多资料,才知道是怎么回事,这里总结一下,记住这个原则就会很清楚了: 1.onInterceptTouchEvent( ...
- Java基础02 方法与数据成员
作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 在Java基础01 从HelloWorld到面向对象,我们初步了解了对象(obje ...