可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
How can I download and save a file to IsolatedStorage
asynchronously? I used WebClient
first for the purpose, but I couldn't await till completion so I found some useful code here.
However, this is also not in complete format. I found the function:
public static Task DownloadFile(Uri url) { var tcs = new TaskCompletionSource(); 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; }
But how can I save this file to IsolatedStorage
? Someone help me to complete this functionality!
回答1:
This, what har07 posted, should work. In case you need to extend your method a little, I would try to do something like this (though it is not tested, but should work):
(Rebuilt after comment - with Cancellation)
// 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 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; } }
I've added Cancellation Token - it means that your download operation can be cancelled after Button.Click. On the other hand if await DownloadFile(uriToDownload) is Cancelled it automatically throws OperationCancelled - then you catch that exception and return adequate result.
I haven't run that code, but it may show the main idea.
回答2:
Try something like this (not tested) :
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]
回答3:
In my opinion best way to use native implementation like this (Wrapping Begin/End asynchronous 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(w.BeginGetResponse, w.EndGetResponse, null); await response.GetResponseStream().CopyToAsync(new FileStream(ApplicationData.Current.LocalFolder.Path + @"\" + fileName, FileMode.CreateNew));