【问题标题】:Save to isolated storage directly in WP8在 WP8 中直接保存到隔离存储
【发布时间】:2014-02-10 07:18:59
【问题描述】:

我想将 zip 文件从服务器直接保存到隔离存储,但我面临的问题是当我尝试使用以下代码保存时,由于我的文件大小有时 > 150 MB,我出现内存不足异常.所以我发布了一个问题here,建议是

您可以将此类文件直接下载到 IsolatedStorage,但如果您想将其放入内存 - 可能会出现问题。

那么我怎样才能将文件从服务器直接保存到隔离存储而不保存到内存。 我使用的代码贴在这里

client = new WebClient();
    client.OpenReadCompleted += new OpenReadCompletedEventHandler(client_OpenReadCompleted);
    client.OpenReadAsync(new Uri(fileurl), objRef);

    private async void client_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
    {

            var file = IsolatedStorageFile.GetUserStoreForApplication();
            if (!file.DirectoryExists("Folderpath/Files"))
            {
                file.CreateDirectory("Folderpath/Files");
            }
            string hpubFile = "/Folderpath/Files/fileName" ;
            using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(hpubFile, System.IO.FileMode.OpenOrCreate, FileAccess.ReadWrite, file))
            {
                byte[] buffer = new byte[1024];
                while (e.Result.Read(buffer, 0, buffer.Length) > 0)
                {
                    stream.Write(buffer, 0, buffer.Length);
                }
            }
        }
    }

【问题讨论】:

  • 你正在从你的服务器获取数据,你想保存在你的应用程序中,而且体积很大
  • 尝试将WebClient的AllowReadStreamBuffering属性设置为false,否则会在引发OpenReadCompleted事件之前下载整个文件
  • @Dragon 是的,我想将远程 url 中的 zip 保存到独立存储中,并且 zip 文件的大小不是一个修复程序。它可能从 10 Mb 到 500 MB 不等
  • @JMat @KooKiz 是对的,首先尝试使用您已有的代码:stackoverflow.com/questions/21572276/…,只需在您的 DownloadFIle 中添加 OpenReadComleted wc.AllowReadStreamBuffering = false;在我发布的答案中流是异步读取的,那么只有缓冲区量应该在内存中,
  • @Romasz 我收到此异常 禁用缓冲时,主线程不支持读取。如果您愿意,我可以共享完整代码

标签: windows-phone-8 webclient isolatedstorage


【解决方案1】:

那么也许可以尝试这种方法 - 用 HttpWebRequest 来做:

    1。首先使用可等待的 GetResponseAsync 扩展您的 HttpWebRequest - WP 缺少此方法,但使用 TaskCompletitionSource 您可以编写自己的实现。在您的命名空间中的某处,创建一个静态类:
public static class Extensions
{
    public static Task<HttpWebResponse> GetResponseAsync(this HttpWebRequest webRequest)
    {
        TaskCompletionSource<HttpWebResponse> taskComplete = new TaskCompletionSource<HttpWebResponse>();
        webRequest.BeginGetResponse(
            asyncResponse =>
            {
                try
                {
                    HttpWebRequest responseRequest = (HttpWebRequest)asyncResponse.AsyncState;
                    HttpWebResponse someResponse = (HttpWebResponse)responseRequest.EndGetResponse(asyncResponse);
                    taskComplete.TrySetResult(someResponse);
                }
                catch (WebException webExc)
                {
                    HttpWebResponse failedResponse = (HttpWebResponse)webExc.Response;
                    taskComplete.TrySetResult(failedResponse);
                }
                catch (Exception exc) { taskComplete.SetException(exc); }
            }, webRequest);
        return taskComplete.Task;
    }
}

    2。然后修改您的代码以使用它:
CancellationTokenSource cts = new CancellationTokenSource();
enum Problem { Ok, Cancelled, Other };

public async Task<Problem> DownloadFileFromWeb(Uri uriToDownload, string fileName, CancellationToken cToken)
{
    try
    {
        HttpWebRequest wbr = WebRequest.CreateHttp(uriToDownload);
        wbr.Method = "GET";
        wbr.AllowReadStreamBuffering = false;
        WebClient wbc = new WebClient();

        using (HttpWebResponse response = await wbr.GetResponseAsync())
        {
            using (Stream mystr = response.GetResponseStream())
            {
                using (IsolatedStorageFile ISF = IsolatedStorageFile.GetUserStoreForApplication())
                  {
                      if (ISF.FileExists(fileName)) return Problem.Other;
                      using (IsolatedStorageFileStream file = ISF.CreateFile(fileName))
                      {
                          const int BUFFER_SIZE = 100 * 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; 
      }
  }

    3。并下载:
  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("Problem with download");
              break;
          case Problem.Cancelled:
              MessageBox.Show("Download cancelled");
              break;
          case Problem.Other:
          default:
              MessageBox.Show("Other problem with download");
              break;
      }
  }

因为我有我的 WebResponse,所以我从中获取一个流,然后异步读取它。
请注意,我没有测试过上面的代码,但希望它能给你一些想法。

【讨论】:

  • 这是迄今为止我发现的最稳定的方法,通过遵循此方法,我能够将大小 > 150 MB 的文件下载到独立存储另一个问题。是否可以跟踪下载操作的进度百分比(向用户显示下载完成量的反馈)
  • @JMat 在这里blogs.msdn.com/b/dotnet/archive/2012/06/06/… 你会找到你需要的一切。
  • 这里 pastebin.com/CsHn938p 是我使用的最终代码,我尝试下载大小为 150 MB 的文件,我注意到一个奇怪的事情,下载返回 OK 状态 @ 64 MB,我重试下载然后它返回好的状态@ 135 MB,我再次尝试下载,然后只下载完整大小,即 15o MB。知道为什么会这样吗? @Romasz
  • @JMat 下载后你检查文件大小了吗?不是这个 labelProgress.Content。
  • 是的,对于小文件,它可以完美运行,但对于较大的文件,它不是,我正在下载一个 zip 文件,我必须在下载后解压缩它。如果下载不完美,我会在解压缩时遇到异常。我正在对此进行更多调查,但没有看到在下载期间暂停执行的任何具体原因。
【解决方案2】:

是的,您可以这样做,您可以先将原始数据保存在 Sqlite 文件中并在代码中使用,然后调用服务器以获取对数据所做的更改并获取这些更新,这样您就不必再次下载数据然后再次.. 此外,如果您必须在每次调用时下载数据,那么您可以使用 sqlite 或 linq。

【讨论】:

  • 但是我的要求不同,我必须将 zip 文件作为文件本身下载并解压缩内容,然后将其保存到独立存储中。也有可能在服务器上修改了 zip 文件,所以我每次请求时都必须下载
  • 也就是说,如果它没有更改预下载文件并保存在代码中的 sqlite 文件中,请打开 sqlite 文件并将数据保存在独立存储中,每次打开应用程序时维护一个检查语句,或者如果有任何更改,请在隔离存储中更改,否则不要下载它。这将帮助您一次又一次地下载数据和时间。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多