2014-02-05 117 views
4

如何異步下載並保存文件到IsolatedStorage? 我首先使用WebClient爲目的,但我不能等待,直到完成,所以我找到了一些有用的代碼here下載並保存Windows Phone 8中的文件異步

但是,這也不是完整的格式。我發現的功能:

public static Task<Stream> DownloadFile(Uri url) 
{ 
    var tcs = new TaskCompletionSource<Stream>(); 
    var wc = new WebClient(); 
    wc.OpenReadCompleted += (s, e) => 
    { 
     if (e.Error != null) tcs.TrySetException(e.Error); 
     else if (e.Cancelled) tcs.TrySetCanceled(); 
     else tcs.TrySetResult(e.Result); 
    }; 
    wc.OpenReadAsync(url); 
    return tcs.Task; 
} 

但是,如何將此文件保存到IsolatedStorage?有人幫我完成這個功能!

+0

在Windows Phone 8中的'WebClient'支持異步編程(見** TaskAsync **後綴方法)。但是,[HttpClient類](http://msdn.microsoft.com/library/system.net.http.httpclient.aspx)可以從[Microsoft HTTP Client Libraries](https:// www。 nuget.org/packages/Microsoft.Net.Http)** NuGet **包更適合異步編程。你的代碼將變得更加乾淨。返回異步方法的Task也應該加後綴** Async **(已經有** Async **後綴方法的'WebClient'例外)。 –

回答

3

這個,貼什麼har07,應該工作。如果你需要擴展你的方法一點點,我會嘗試做這樣的事情(儘管它沒有進行測試,但應工作):

(評論重修後 - 與取消)

// first define Cancellation Token Source - I've made it global so that CancelButton has acces to it 
CancellationTokenSource cts = new CancellationTokenSource(); 
enum Problem { Ok, Cancelled, Other }; // results of my Task 

// cancelling button event 
private void CancellButton_Click(object sender, RoutedEventArgs e) 
{ 
    if (this.cts != null) 
     this.cts.Cancel(); 
} 

// the main method - I've described it a little below in the text 
public async Task<Problem> DownloadFileFromWeb(Uri uriToDownload, string fileName, CancellationToken cToken) 
{ 
    try 
    { 
     using (Stream mystr = await DownloadFile(uriToDownload)) 
      using (IsolatedStorageFile ISF = IsolatedStorageFile.GetUserStoreForApplication()) 
      { 
      if (ISF.FileExists(fileName)) return Problem.Other; 
      using (IsolatedStorageFileStream file = ISF.CreateFile(fileName)) 
      { 
       const int BUFFER_SIZE = 1024; 
       byte[] buf = new byte[BUFFER_SIZE]; 

       int bytesread = 0; 
       while ((bytesread = await mystr.ReadAsync(buf, 0, BUFFER_SIZE)) > 0) 
       { 
        cToken.ThrowIfCancellationRequested(); 
        file.Write(buf, 0, bytesread); 
       } 
      } 
     } 
     return Problem.Ok; 
    } 
    catch (Exception exc) 
    { 
     if (exc is OperationCanceledException) 
      return Problem.Cancelled; 
     else return Problem.Other; 
    } 
} 

// and download 
private async void Downlaod_Click(object sender, RoutedEventArgs e) 
{ 
    cts = new CancellationTokenSource(); 
    Problem fileDownloaded = await DownloadFileFromWeb(new Uri(@"http://filedress/myfile.txt", UriKind.Absolute), "myfile.txt", cts.Token); 
    switch(fileDownloaded) 
    { 
     case Problem.Ok: 
      MessageBox.Show("File downloaded"); 
      break; 
     case Problem.Cancelled: 
      MessageBox.Show("Download cancelled"); 
      break; 
     case Problem.Other: 
     default: 
      MessageBox.Show("Other problem with download"); 
      break; 
    } 
} 

我添加了取消令牌 - 這意味着您的下載操作可以在Button.Click後取消。另一方面,如果等待DownloadFile(uriToDownload)被取消,它會自動拋出OperationCancelled - 然後你捕獲該異常並返回足夠的結果。

我還沒有運行該代碼,但它可能會顯示主要想法。

+0

我們如何處理在這種情況下取​​消webclient下載。我設置if(e.Cancelled)tcs.TrySetCanceled();. BUt我該如何檢查主線程 –

+0

@JMat我編輯了我的答案,並試圖添加取消功能。可能會有一些錯誤(我沒有運行它) - 但希望你能得到主要想法。 – Romasz

+0

是的,它工作,我正在努力與一個奇怪的問題,同時下載文件OutOf內存異常。如果你有一些建議,請發表評論http://stackoverflow.com/questions/21594417/outofmemoryexception-while-downloading-files-wp8 –

3

嘗試這樣的事情(未測試):

try 
{ 
    using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication()) 
    { 
     IsolatedStorageFileStream fileStream = myIsolatedStorage.CreateFile("fileNameHere"); 

     BitmapImage bitmap = new BitmapImage(); 
     var stream = await DownloadFile(new Uri("http://someuri.com", UriKind.Absolute)); 
     bitmap.SetSource(stream); 
     WriteableBitmap wb = new WriteableBitmap(bitmap); 

     // Encode WriteableBitmap object to a JPEG stream. 
     Extensions.SaveJpeg(wb, fileStream, wb.PixelWidth, wb.PixelHeight, 0, 85); 
     fileStream.Close(); 
    } 
} 
catch (Exception ex) 
{ 
    //Exception handle appropriately for your app 
} 

[Reference]

-1

在我使用本機實現這樣的觀點最好的方式(包裝紙開始/結束異步API):基於任務

var url = new Uri(UriString, UriKind.Absolute); 
var fileName = Path.GetFileName(url.LocalPath); 

var w = WebRequest.CreateHttp(url); 
var response = await Task.Factory.FromAsync<WebResponse>(w.BeginGetResponse, w.EndGetResponse, null); 
await response.GetResponseStream().CopyToAsync(new FileStream(ApplicationData.Current.LocalFolder.Path + @"\" + fileName, FileMode.CreateNew)); 
+0

在這個問題中,您已經鏈接了該問題的副本,請將其標記爲重複副本,而不是留下相應的答案。如果它不是重複的,請留下一個完整的答案,而不是隻有鏈接的答案。 – josliber

相關問題