windows phone 8:如何从web下载xml文件并将其保存到本地?

Car*_* Vo 3 windows-phone-8

我想从网上下载一个xml文件,然后将其保存到本地存储,但我不知道该怎么做.请帮我清楚或给我一个例子.谢谢.

Rom*_*asz 5

下载文件是一个很大的主题,可以通过多种方式完成.我假设你知道你要下载的文件的Uri,并希望你的意思是本地IsolatedStorage.

我将展示三个例子如何完成(还有其他方法).

1.最简单的示例将通过WebClient下载字符串:

public static void DownloadFileVerySimle(Uri fileAdress, string fileName)
{
   WebClient client = new WebClient();
   client.DownloadStringCompleted += (s, ev) =>
   {
       using (IsolatedStorageFile ISF = IsolatedStorageFile.GetUserStoreForApplication())
       using (StreamWriter writeToFile = new StreamWriter(ISF.CreateFile(fileName)))
           writeToFile.Write(ev.Result);
   };
   client.DownloadStringAsync(fileAdress);
}
Run Code Online (Sandbox Code Playgroud)

正如你所看到的那样,我正在直接下载字符串(这ev.Result是一种string- 这是这种方法的一个缺点)到IsolatedStorage.和用法 - 例如按钮点击后:

private void Download_Click(object sender, RoutedEventArgs e)
{
   DownloadFileVerySimle(new Uri(@"http://filedress/myfile.txt", UriKind.Absolute), "myfile.txt");
}
Run Code Online (Sandbox Code Playgroud)

2.在第二种方法(简单但更复杂)我将再次使用WebClient,我将需要异步(如果你是新手,我建议阅读MSDN,async-await在Stephen Cleary博客上,也许是一些教程).

首先,我需要从网上Task下载Stream:

public static Task<Stream> DownloadStream(Uri url)
{
   TaskCompletionSource<Stream> tcs = new TaskCompletionSource<Stream>();
   WebClient wbc = new WebClient();
   wbc.OpenReadCompleted += (s, e) =>
   {
      if (e.Error != null) tcs.TrySetException(e.Error);
      else if (e.Cancelled) tcs.TrySetCanceled();
      else tcs.TrySetResult(e.Result);
   };
   wbc.OpenReadAsync(url);
   return tcs.Task;
}
Run Code Online (Sandbox Code Playgroud)

然后我会写下我的方法下载文件 - 它也需要异步,因为我将使用await DownloadStream:

public enum DownloadStatus { Ok, Error };

public static async Task<DownloadStatus> DownloadFileSimle(Uri fileAdress, string fileName)
{
   try
   {
       using (Stream resopnse = await DownloadStream(new Uri(@"http://filedress/myfile.txt", UriKind.Absolute)))
         using (IsolatedStorageFile ISF = IsolatedStorageFile.GetUserStoreForApplication())
         {
            if (ISF.FileExists(fileName)) return DownloadStatus.Error;
            using (IsolatedStorageFileStream file = ISF.CreateFile(fileName))
                resopnse.CopyTo(file, 1024);
            return DownloadStatus.Ok;
         }
   }
   catch { return DownloadStatus.Error; }
}
Run Code Online (Sandbox Code Playgroud)

然后在按钮点击后使用我的方法:

private async void Downlaod_Click(object sender, RoutedEventArgs e)
{
   DownloadStatus fileDownloaded = await DownloadFileSimle(new Uri(@"http://filedress/myfile.txt", UriKind.Absolute), "myfile.txt");
   switch (fileDownloaded)
   {
       case DownloadStatus.Ok:
            MessageBox.Show("File downloaded!");
            break;
       case DownloadStatus.Error:
       default:
            MessageBox.Show("There was an error while downloading.");
            break;
    }
}
Run Code Online (Sandbox Code Playgroud)

例如,如果您尝试下载非常大的文件(例如150 Mb),则此方法可能会出现问题.

3.第三种方法 - 再次使用WebRequest和async-await,但是可以通过缓冲区更改此方法以下载文件,因此不要使用太多内存:

首先,我需要Webrequest通过一个异步返回的方法来扩展我Stream:

public static class Extensions
{
    public static Task<Stream> GetRequestStreamAsync(this WebRequest webRequest)
    {
        TaskCompletionSource<Stream> taskComplete = new TaskCompletionSource<Stream>();
        webRequest.BeginGetRequestStream(arg =>
        {
            try
            {
                Stream requestStream = webRequest.EndGetRequestStream(arg);
                taskComplete.TrySetResult(requestStream);
            }
            catch (Exception ex) { taskComplete.SetException(ex); }
        }, webRequest);
        return taskComplete.Task;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我可以开始工作并编写我的下载方法:

public static async Task<DownloadStatus> DownloadFile(Uri fileAdress, string fileName)
{
   try
   {
      WebRequest request = WebRequest.Create(fileAdress);
      if (request != null)
      {
          using (Stream resopnse = await request.GetRequestStreamAsync())
          {
             using (IsolatedStorageFile ISF = IsolatedStorageFile.GetUserStoreForApplication())
             {
                  if (ISF.FileExists(fileName)) return DownloadStatus.Error;
                    using (IsolatedStorageFileStream file = ISF.CreateFile(fileName))
                    {
                       const int BUFFER_SIZE = 10 * 1024;
                       byte[] buf = new byte[BUFFER_SIZE];

                       int bytesread = 0;
                       while ((bytesread = await resopnse.ReadAsync(buf, 0, BUFFER_SIZE)) > 0)
                                file.Write(buf, 0, bytesread);
                   }
             }
             return DownloadStatus.Ok;
         }
     }
     return DownloadStatus.Error;
  }
  catch { return DownloadStatus.Error; }
}
Run Code Online (Sandbox Code Playgroud)

再次使用:

private async void Downlaod_Click(object sender, RoutedEventArgs e)
{
   DownloadStatus fileDownloaded = await DownloadFile(new Uri(@"http://filedress/myfile.txt", UriKind.Absolute), "myfile.txt");
   switch (fileDownloaded)
   {
       case DownloadStatus.Ok:
           MessageBox.Show("File downloaded!");
           break;
       case DownloadStatus.Error:
       default:
           MessageBox.Show("There was an error while downloading.");
           break;
   }
}
Run Code Online (Sandbox Code Playgroud)

这些方法当然可以改进,但我认为这可以让你概述它的外观.这些方法的主要缺点可能是它们在前台工作,这意味着当您退出应用程序或点击开始按钮时,下载停止.如果您需要在后台下载,您可以使用后台文件传输 - 但这是其他故事.

如您所见,您可以通过多种方式实现目标.您可以在许多页面,教程和博客上阅读有关这些方法的更多信息,比较选择最合适的方法.

希望这可以帮助.快乐的编码和祝你好运.

  • @Carson IsolatedStorage文件夹位于您的手机中,即"地点"严格连接到您的应用程序,没有其他应用程序可以访问它.但是,您可以通过[IsolatedStorage Explorer](http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh286408(v = vs.105).aspx)探索您的开发人员设备(或模拟器)或例如,通过[IsolatedStorage Spy](http://isostorespy.codeplex.com/). (2认同)
  • @Carson然后你发现了下载字符串的下一个不幸事件;) - 字符串可以有不同的编码.要解决您的问题,您可能只需要更改streamwriter的编码,下面的行应该修复您的文件大小:using(StreamWriter writeToFile = new StreamWriter(ISF.CreateFile(fileName),Encoding.Unicode)) (2认同)