zoukankan      html  css  js  c++  java
  • 与众不同 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 == 200 || transfer.StatusCode == 206)
                        {
                            // 下载完成后不会自动从队列中删除,需要手动删除
                            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("https://files.cnblogs.com/webabcd/Silverlight.rar", UriKind.Absolute));
    
                UpdateUI();
            }
    
            private void btnDownloadXNADemo_Click(object sender, RoutedEventArgs e)
            {
                AddBackgroundTransfer("XNA.rar", new Uri("https://files.cnblogs.com/webabcd/XNA.rar", UriKind.Absolute));
    
                UpdateUI();
            }
    
            private void btnDownloadWindowsPhoneDemo_Click(object sender, RoutedEventArgs e)
            {
                AddBackgroundTransfer("WindowsPhone.rar", new Uri("https://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() >= 5)
                {
                    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 == 200)
                        {
                            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 > 0)
                {
                    // 保存上传过来的文件
                    byte[] data = Request.BinaryRead(Request.TotalBytes);
                    File.WriteAllBytes(@"C:\" + Request.QueryString["fileName"], data);
                }
            }
        }
    }


    OK
    [源码下载]

  • 相关阅读:
    文件隐藏在一张图片里
    晶振
    主宰全球的10大算法
    java+mysql连接的优化
    排序剔除
    js数据类型
    字符实体
    表单
    定义样式表
    布局相关的属性
  • 原文地址:https://www.cnblogs.com/webabcd/p/2592989.html
Copyright © 2011-2022 走看看