介紹
重新想象 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
<Page x:Class="XamlDemo.BackgroundTask.TransferDownload" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:XamlDemo.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="120 0 0 0"> <ScrollViewer Height="100"> <TextBlock Name="lblMsg" FontSize="14.667" TextWrapping="Wrap" /> </ScrollViewer> <Button Name="btnAddDownload" Content="新增一個下載任務" Margin="0 10 0 0" Click="btnAddDownload_Click" /> <Button Name="btnPause" Content="暫停所有下載任務" Margin="0 10 0 0" Click="btnPause_Click" /> <Button Name="btnResume" Content="繼續所有下載任務" Margin="0 10 0 0" Click="btnResume_Click" /> <Button Name="btnCancel" Content="取消所有下載任務" Margin="0 10 0 0" Click="btnCancel_Click" /> <ListView Name="listView" Padding="0 10 0 0" Height="300"> <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/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<DownloadOperation, DownloadOperation> 對象 * AttachAsync() - 監視已存在的下載任務,返回 IAsyncOperationWithProgress<DownloadOperation, DownloadOperation> 對象 * 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<TransferModel> _transfers = new ObservableCollection<TransferModel>(); // 所有下載任務的關聯的 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<DownloadOperation> downloads = null; try { // 獲取所有後台下載任務 downloads = await BackgroundDownloader.GetCurrentDownloadsAsync(); } catch (Exception ex) { lblMsg.Text += ex.ToString(); lblMsg.Text += Environment.NewLine; return; } if (downloads.Count > 0) { List<Task> tasks = new List<Task>(); 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 類型文件的關聯) // 查看本欄目
<Page x:Class="XamlDemo.BackgroundTask.TransferUpload" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:XamlDemo.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="120 0 0 0"> <ScrollViewer Height="100"> <TextBlock Name="lblMsg" FontSize="14.667" TextWrapping="Wrap" /> </ScrollViewer> <Button Name="btnAddUpload" Content="新增一個上傳任務(一次請求上傳一個文件)" Margin="0 10 0 0" Click="btnAddUpload_Click" /> <Button Name="btnAddMultiUpload" Content="新增一個上傳任務(一次請求上傳多個文件)" Margin="0 10 0 0" Click="btnAddMultiUpload_Click" /> <Button Name="btnCancel" Content="取消所有上傳任務" Margin="0 10 0 0" Click="btnCancel_Click" /> <ListView Name="listView" Padding="0 10 0 0" Height="300"> <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
/* * 演示後台上傳任務的應用 * * 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<BackgroundTransferContentPart> 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<UploadOperation, UploadOperation> 對象 * AttachAsync() - 監視已存在的上傳任務,返回 IAsyncOperationWithProgress<UploadOperation, UploadOperation> 對象 * 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<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) { lblMsg.Text += ex.ToString(); lblMsg.Text += Environment.NewLine; return; } if (uploads.Count > 0) { 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: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<StorageFile> sourceFiles = new List<StorageFile>(); 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<BackgroundTransferContentPart> contentParts = new List<BackgroundTransferContentPart>(); for (int i = 0; i < sourceFiles.Count; i++) { BackgroundTransferContentPart contentPart = new BackgroundTransferContentPart("File" + i, sourceFiles[i].Name); contentPart.SetFile(sourceFiles[i]); contentParts.Add(contentPart); } // 創建一個後台上傳任務,此任務包含多個上傳文件 BackgroundUploader backgroundUploader = new BackgroundUploader(); 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 = "0 / 0"; _transfers.Add(transfer); lblMsg.Text += "Task Count: " + _transfers.Count.ToString(); lblMsg.Text += Environment.NewLine; // 當上傳進度發生變化時的回調函數 Progress<UploadOperation> progressCallback = new Progress<UploadOperation>(UploadProgress); if (isNew) await upload.StartAsync().AsTask(_cancelToken.Token, progressCallback); // 新增一個後台上傳任務 else await upload.AttachAsync().AsTask(_cancelToken.Token, progressCallback); // 監視已存在的後台上傳任務 // 上傳完成後獲取服務端的響應信息 // 查看本欄目
/* * 用於接收上傳文件的服務 */ 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[i]; 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
源碼下載:http://files.cnblogs.com/webabcd/Windows8.rar