原文:与众不同 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(后台任务)之后台文件传输(上传和下载)的更多相关文章

  1. 与众不同 windows phone (12) - Background Task(后台任务)之 PeriodicTask(周期任务)和 ResourceIntensiveTask(资源密集型任务)

    原文:与众不同 windows phone (12) - Background Task(后台任务)之 PeriodicTask(周期任务)和 ResourceIntensiveTask(资源密集型任 ...

  2. 与众不同 windows phone (11) - Background Task(后台任务)之警报(Alarm)和提醒(Reminder)

    原文:与众不同 windows phone (11) - Background Task(后台任务)之警报(Alarm)和提醒(Reminder) [索引页][源码下载] 与众不同 windows p ...

  3. Xshell在Windows和Linux间文件的上传和下载

    本文通过lrzsz来实现Windows和Linux间文件间的文件传输. lrzsz使用 XMODEM.YMODEM 和 ZMODEM 文件传输协议来实现文件的上传和下载.相比 FTP 或者 WinSC ...

  4. 记crt 在windows与linux服务器之间利用ftp进行文件的上传下载

    我们首先来熟悉一些相关的命令以及操作: ls      #展示linux服务器当前工作目录[你连接sftp时所处的目录]下的所有文件以及文件夹 lcd  F:\niki      #绑定你在windo ...

  5. windows下实现linux的远程访问以及linux上文件的上传和下载

    在网络性能.安全性.可管理性上,Linux有着其他系统无法比拟的强大优势,而服务器对这些方面要求特别高,因此Linux常常被用来做服务器使用.而当我们需要维护linux服务器的时候,就需要远程访问li ...

  6. windows下定时利用bat脚本实现ftp上传和下载

    前言: 工作中可能会遇到以下情况,利用windows作为中转,来实现两台linux服务器的文件传输. 实现步骤: 1.FTP上传和下载的bat脚本. 脚本分为两部分:可执行bat脚本和ftp命令文件: ...

  7. Git Gui for Windows的建库、克隆(clone)、上传(push)、下载(pull)、合并(转)

    Git Gui for Windows的建库.克隆(clone).上传(push).下载(pull).合并(转) from:http://hi.baidu.com/mvp_xuan/blog/item ...

  8. Windows到Linux的文件上传、下载

    1.使用我们常用的Xshell登录工具,新建立一个远程会话,填写ip地址及用户名密码后,选择最下面的ZMODEM,填写下载的路径.加载的路径:2个路径可以一样也可以不一样: 2.在Linux主机上,安 ...

  9. 在windows和linux之间用SecureCRT来上传和下载文件

    SecureCRT可以使用linux下的zmodem协议来快速的传送文件,使用非常方便.具体步骤:一.在使用SecureCRT上传下载之前需要给服务器安装lrzsz:A:CentOS中使用yum安装即 ...

随机推荐

  1. Spring Web MVC中的页面缓存支持 ——跟我学SpringMVC系列

    Spring Web MVC中的页面缓存支持 ——跟我学SpringMVC系列

  2. Python 数据分析(二 本实验将学习利用 Python 数据聚合与分组运算,时间序列,金融与经济数据应用等相关知识

    Python 数据分析(二) 本实验将学习利用 Python 数据聚合与分组运算,时间序列,金融与经济数据应用等相关知识 第1节 groupby 技术 第2节 数据聚合 第3节 分组级运算和转换 第4 ...

  3. 求 n! (大数问题)----------HDOJ1042

    以下只YY算法,c++实现,java大神绕道..... (1)位数的估计     显然对于大数(比如1000的阶乘)的阶乘我们找不到一个数据类型存放这个数,是在太大啦....     那么现在来估计一 ...

  4. J2EE基础篇——十三个规范

    背景: 1.企业级应用框架的需求,在很多企业级应用中.比如数据库连接.邮件服务.事务处理等都是一些通用企业需求模块,这些模块假设每次在开发中都由开发者来完毕的话,将会造成开发周期长和代码可靠性差等问题 ...

  5. 【Cocos2d-x】截图分享功能

    Cocos2d-x截图实现 图片将会保存在data/data/包名/files文件夹下. Android下分享一张图片 linux系统下的文件权限 普通情况下android下的每个应用程序都是一个独立 ...

  6. 使用内容提供者和xml备份联系人

    1.通过内容提供者获取联系人信息 package com.ithaimazyh.readcontact; import java.util.ArrayList; import java.util.Li ...

  7. 集合简单总结 ArrayList、List、Hashtable、Dictionary

      ============================ 集合综述 ============================== 1.什么是泛型: 泛型就是限制了操作类型,意思如下:       ...

  8. 图示CCScrollView的相关概念

    (转载请注明原文地址:http://blog.csdn.net/while0/article/details/11527899) 见下图: 1)设置ScrollView的视口大小的函数是:setVie ...

  9. jQuery.mobile.changePage() | jQuery Mobile API Documentation

    jQuery.mobile.changePage() | jQuery Mobile API Documentation <script> $.mobile.changePage( &qu ...

  10. [置顶] Guava学习之Lists

    Lists类主要提供了对List类的子类构造以及操作的静态方法.在Lists类中支持构造ArrayList.LinkedList以及newCopyOnWriteArrayList对象的方法.其中提供了 ...