標籤:win8 離線緩衝
我們在開發市集應用時,需要app具有緩衝的功能,這樣在離線模式下,仍能工作。我們選擇的project為Hub。
這裡採取的策略是:在HubPage.xaml.cs(之所以不選擇App.xaml.cs,是為了能讓使用者一邊操作介面一邊進行下載)中,利用await非同步編程,避免阻塞UI,先讀取存有圖片路徑的JSON,然後解析該JSON得到每一張圖片的URI,再根據URI下載圖片,對於文字資源,直接下載JSON。這裡要特別注意檔案操作——檔案許可權,同時更要注意檔案流的選取——如果選擇不當會導致在下載圖片時偶然性僵死。
在HubPage.xaml.cs中:
using Bing.Maps;using demo02.Common;using demo02.Data;using demo02.DataModel;using demo02.DataStructure;using demo02.Entity;using demo02.Helper;using Newtonsoft.Json;using System;using System.Collections.Generic;using System.Collections.ObjectModel;using System.IO;using System.Linq;using System.Net.Http;using System.Runtime.InteropServices.WindowsRuntime;using System.Threading.Tasks;using WhereWeGo.Helper;using Windows.ApplicationModel.Search;using Windows.Foundation;using Windows.Foundation.Collections;using Windows.Storage;using Windows.UI;using Windows.UI.Popups;using Windows.UI.Xaml;using Windows.UI.Xaml.Controls;using Windows.UI.Xaml.Controls.Primitives;using Windows.UI.Xaml.Data;using Windows.UI.Xaml.Input;using Windows.UI.Xaml.Media;using Windows.UI.Xaml.Media.Animation;using Windows.UI.Xaml.Navigation;//“中心頁”項目範本在 http://go.microsoft.com/fwlink/?LinkID=321224 上有介紹namespace demo02{ public sealed partial class HubPage : Page { //一個容器,裡面存有每個圖片的url對象//將JSON中存的圖片的uri讀取到PicArray,然後通過PicArray下載圖片 private static OfflinePicArray PicArray { get; set; } private NavigationHelper navigationHelper; private ObservableDictionary defaultViewModel = new ObservableDictionary(); public HubPage() { this.InitializeComponent(); this.navigationHelper = new NavigationHelper(this); this.navigationHelper.LoadState += navigationHelper_LoadState; } private async void navigationHelper_LoadState(object sender, LoadStateEventArgs e) { if (ConnectState.isConnected) //如果網路是串連的,進行緩衝下載 { if (OfflineFirstFlag.isFirstEnter) //由於之後會多次進入HubPage頁面,我們只應當在第一次進入頁面時進行下載 { OfflineFirstFlag.isFirstEnter = false;//獲得圖片資源,先下載存有uri的JSON,再解析JSON,再通過解析出的uri下載圖片 //擷取存有用於離線模式片uri的JSON await HttpGetOfflinePICSJSON(); //擷取存有老師和地區圖片的url的JSON await HttpGetOfflineTeacherRegionJSON(); //獲得第一部分圖片 await HttpGetOfflingPicByUrl();//獲得第二部分圖片 await HttpGetOfflingPicByUrl02();//獲得第三部分圖片 await HttpGetOfflingPicByUrl03();//獲得第四部分圖片 await HttpGetOfflingPicByUrl04();//獲得文字資源 //獲得離線模式資料展示的來源JSON await HttpGetOfflineJSON(); } } } //向伺服器請求最新的PICS JSON private async static Task HttpGetOfflinePICSJSON() { XDownload xmen = new XDownload(ServiceUrl.URL_OFFLINE_PICSJSON, XDownload.App, OfflineSubFolder.Name, ServiceUrl.PICSJSON_LOCALNAME); await xmen.GetDataAsync(); } private async static Task HttpGetOfflingPicByUrl() { try { StorageFolder storageFolder = Windows.ApplicationModel.Package.Current.InstalledLocation; StorageFolder folder = await storageFolder.GetFolderAsync(OfflineSubFolder.Name); StorageFile storageFile = await folder.GetFileAsync(ServiceUrl.PICSJSON_LOCALNAME); if (storageFile != null) { XDownload bigOverhead = new XDownload(); bigOverhead.Library = XDownload.App; bigOverhead.Myfolder = OfflineSubFolder.Name; // 擷取指定的檔案中的常值內容 string textContent = await FileIO.ReadTextAsync(storageFile, Windows.Storage.Streams.UnicodeEncoding.Utf8); PicArray = JsonConvert.DeserializeObject<OfflinePicArray>(textContent); foreach (OfflinePicUri onePic in PicArray.Images) { foreach (string picName in onePic.ShowImages) { if (picName != null) { bigOverhead.Uri = ServiceUrl.BASEURL_OFFLINE + onePic.ImageFolder + picName; System.Diagnostics.Debug.WriteLine(bigOverhead.Uri + "kakakakakakkakakak"); bigOverhead.Filename = picName; await bigOverhead.GetDataAsync(); } } } } catch(Exception ex) { } } private async static Task HttpGetOfflingPicByUrl02() { try { StorageFolder storageFolder = Windows.ApplicationModel.Package.Current.InstalledLocation; StorageFolder folder = await storageFolder.GetFolderAsync(OfflineSubFolder.Name); StorageFile storageFile = await folder.GetFileAsync(ServiceUrl.PICSJSON_LOCALNAME); if (storageFile != null) { XDownload bigOverhead = new XDownload(); bigOverhead.Library = XDownload.App; bigOverhead.Myfolder = OfflineSubFolder.Name; // 擷取指定的檔案中的常值內容 string textContent = await FileIO.ReadTextAsync(storageFile, Windows.Storage.Streams.UnicodeEncoding.Utf8); PicArray = JsonConvert.DeserializeObject<OfflinePicArray>(textContent); foreach (OfflinePicUri onePic in PicArray.Images) { if (onePic.TileImagePath != null) { bigOverhead.Uri = ServiceUrl.BASEURL_OFFLINE + onePic.ImageFolder + onePic.TileImagePath; bigOverhead.Filename = onePic.TileImagePath; await bigOverhead.GetDataAsync(); } } } } catch (Exception ex) { } } private async static Task HttpGetOfflingPicByUrl03() { try { StorageFolder storageFolder = Windows.ApplicationModel.Package.Current.InstalledLocation; StorageFolder folder = await storageFolder.GetFolderAsync(OfflineSubFolder.Name); StorageFile storageFile = await folder.GetFileAsync(ServiceUrl.PICSJSON_LOCALNAME); if (storageFile != null) { XDownload bigOverhead = new XDownload(); bigOverhead.Library = XDownload.App; bigOverhead.Myfolder = OfflineSubFolder.Name; // 擷取指定的檔案中的常值內容 string textContent = await FileIO.ReadTextAsync(storageFile, Windows.Storage.Streams.UnicodeEncoding.Utf8); PicArray = JsonConvert.DeserializeObject<OfflinePicArray>(textContent); foreach (OfflinePicUri onePic in PicArray.Images) { if (onePic.Badge != null) { bigOverhead.Uri = ServiceUrl.BASEURL_OFFLINE + onePic.ImageFolder + onePic.Badge; bigOverhead.Filename = onePic.Badge; await bigOverhead.GetDataAsync(); } } } } catch(Exception ex) { } } private async Task HttpGetOfflingPicByUrl04() { try { StorageFolder storageFolder = Windows.ApplicationModel.Package.Current.InstalledLocation; StorageFolder folder = await storageFolder.GetFolderAsync(OfflineSubFolder.Name); //接著下載老師和地區的圖片 StorageFile storageFile01 = await folder.GetFileAsync(ServiceUrl.T_R_JSON_LOCALNAME); if (storageFile01 != null) { XDownload bigOverhead = new XDownload(); bigOverhead.Library = XDownload.App; bigOverhead.Myfolder = OfflineSubFolder.Name; // 擷取指定的檔案中的常值內容 string textContent = await FileIO.ReadTextAsync(storageFile01, Windows.Storage.Streams.UnicodeEncoding.Utf8); TRPic tr = new TRPic(); tr = JsonConvert.DeserializeObject<TRPic>(textContent); foreach (string onePic in tr.TeacherImages) { //開始下載圖片 bigOverhead.Uri = ServiceUrl.BASEURL_OFFLINE + onePic; bigOverhead.Filename = TeaRegFilter.GetPicName(onePic); await bigOverhead.GetDataAsync(); } } }catch (Exception ex) { } } private async static Task HttpGetOfflineJSON() { XDownload xmen = new XDownload(ServiceUrl.URL_OFFLINE_JSON, XDownload.App, OfflineSubFolder.Name, ServiceUrl.JSON_LOCALNAME); await xmen.GetDataAsync(); } private async static Task HttpGetOfflineTeacherRegionJSON() { XDownload xmen = new XDownload(ServiceUrl.URL_OFFLINE_TEACHER_REGION_JSON, XDownload.App, OfflineSubFolder.Name, ServiceUrl.T_R_JSON_LOCALNAME); await xmen.GetDataAsync(); } }}using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Net.Http;using System.Text;using System.Threading.Tasks;using Windows.Networking.BackgroundTransfer;using Windows.Storage;using Windows.Storage.Streams;namespace demo02.Helper{ //該類的作用是將伺服器端的檔案uri通過http下載到本地指定目錄,並命名 public class XDownload { public static string Documents = "Documents"; public static string Pictures = "Pictures"; public static string Music = "Music"; public static string Videos = "Videos"; public static string App = "App"; public XDownload() { this.Uri = ""; this.Library = ""; this.Myfolder = ""; this.Filename = ""; } public XDownload(String uri, String library, String myfolder, String filename) { this.Uri = uri; this.Library = library; this.Myfolder = myfolder; this.Filename = filename; } //不帶傳回值的Task public async Task GetDataAsync() { StorageFolder folder = null; try { switch (this.Library) { case "Documents": folder = KnownFolders.DocumentsLibrary; break; case "Pictures": folder = KnownFolders.PicturesLibrary; break; case "Music": folder = KnownFolders.MusicLibrary; break; case "Videos": folder = KnownFolders.VideosLibrary; break; case "App":folder = Windows.ApplicationModel.Package.Current.InstalledLocation; //C:\Users\tom\Documents\GitHub\wherewegov1\wherewego\demo02\bin\Debug\AppXbreak; default: System.Diagnostics.Debug.WriteLine("ERROR: Make sure you are using the four special library: Documents, Music, Videos, Pictures"); return; } if (this.Myfolder == "") { System.Diagnostics.Debug.WriteLine("ERROR: Make sure you input a valid subfolder"); return; } StorageFolder childFolder = await folder.CreateFolderAsync(this.Myfolder, CreationCollisionOption.OpenIfExists); if (this.Filename == "") { System.Diagnostics.Debug.WriteLine("ERROR: Make sure you input a valid filename"); return; } //Creates a new file in the current folder, and specifies what to do if //a file with the same name already exists in the current folder. StorageFile outputFile = await childFolder.CreateFileAsync(this.Filename, CreationCollisionOption.ReplaceExisting); //選擇恰當的流,避免下載圖片過程中僵死var fs = await outputFile.OpenAsync(FileAccessMode.ReadWrite); HttpClientHandler handler = new HttpClientHandler(); handler.ClientCertificateOptions = ClientCertificateOption.Automatic; HttpClient hc = new HttpClient(handler); HttpResponseMessage response = await hc.GetAsync(this.Uri, HttpCompletionOption.ResponseHeadersRead); Stream stream = await response.Content.ReadAsStreamAsync(); IInputStream inputStream = stream.AsInputStream(); ulong totalBytesRead = 0; while (true) { // Read from the web. IBuffer buffer = new Windows.Storage.Streams.Buffer(1024); buffer = await inputStream.ReadAsync( buffer, buffer.Capacity, InputStreamOptions.None); if (buffer.Length == 0) { // 完成 break; } // 進度 totalBytesRead += buffer.Length; System.Diagnostics.Debug.WriteLine("Bytes read: {0}", totalBytesRead); // 寫檔案. await fs.WriteAsync(buffer); } inputStream.Dispose(); fs.Dispose(); } catch (Exception) { System.Diagnostics.Debug.WriteLine("ERROR: file download failed, tai can le"); } } public string Uri { get; set; } public string Library { get; set; } public string Myfolder { get; set; } public string Filename { get; set; } }}