2014-02-05 73 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

相关问题