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
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<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;
}
}
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.
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]
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<WebResponse>(w.BeginGetResponse, w.EndGetResponse, null);
await response.GetResponseStream().CopyToAsync(new FileStream(ApplicationData.Current.LocalFolder.Path + @"\" + fileName, FileMode.CreateNew));