-->

按块下载文件(Windows手机)(Download file in chunks (Windows

2019-07-19 00:19发布

在我的应用程序可以从网上下载一些媒体文件。 通常我用WebClient.OpenReadCompleted方法下载,解密和保存文件到IsolatedStorage。 它运作良好,并期待这样的:

 private void downloadedSong_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e, SomeOtherValues someOtherValues) // delegate, uses additional values
        {
            // Some preparations

                try
                {
                   if (e.Result != null)
                   {
                    using (isolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication())
                    {
                        // working with the gained stream, decryption
                        // saving the decrypted file to isolatedStorage
                        isolatedStorageFileStream = new IsolatedStorageFileStream("SomeFileNameHere", FileMode.OpenOrCreate, isolatedStorageFile);
                        // and use it for MediaElement
                        mediaElement.SetSource(isolatedStorageFileStream);
                        mediaElement.Position = new TimeSpan(0);
                        mediaElement.MediaOpened += new RoutedEventHandler(mediaFile_MediaOpened);

                        // and some other work
                     }
                    }
                 }
                 catch(Exception ex) 
                 {
                  // try/catch stuff
                 }
           }

但经过一番调查,我发现,与大文件(对我来说这是超过100 MB)下载此文件中我得到了OutOfMemory例外。 我想这是因为WebClient.OpenReadCompleted加载整个流进RAM和扼流圈......我需要更多的内存来解密此流。

又经过调查,我发现了如何在这个文件保存到IsolatedStorage(或解密,然后在我的OCASION保存)将大型文件分成OpenReadCompleted事件之后块,但这仅仅的问题......主要部分帮助问题是如何防止在下载过程中手机扼流圈有没有一种方法来下载大文件的块? 然后,我可以用找到的解决方案,通过解密过程。 (和仍然我需要找到一种方式来加载这么大的文件到MediaElement的,但是这将是另一个问题)


回答:

 private WebHeaderCollection headers;
 private int iterator = 0;
 private int delta = 1048576;
 private string savedFile = "testFile.mp3";

 // some preparations
 // Start downloading first piece


using (IsolatedStorageFile isolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication())
                    {
                        if (isolatedStorageFile.FileExists(savedFile))
                            isolatedStorageFile.DeleteFile(savedFile);
                    }

                    headers = new WebHeaderCollection();
                    headers[HttpRequestHeader.Range] = "bytes=" + iterator.ToString() + '-' + (iterator + delta).ToString();
                    webClientReadCompleted = new WebClient();
                    webClientReadCompleted.Headers = headers;
                    webClientReadCompleted.OpenReadCompleted += downloadedSong_OpenReadCompleted;
                    webClientReadCompleted.OpenReadAsync(new Uri(song.Link));
                    // song.Link was given earlier

private void downloadedSong_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
        {
            try
            {
                if (e.Cancelled == false)
                {
                    if (e.Result != null)
                    {
                        ((WebClient)sender).OpenReadCompleted -= downloadedSong_OpenReadCompleted;

                        using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
                        {
                            using (IsolatedStorageFileStream fileStream = new IsolatedStorageFileStream(savedFile, FileMode.Append, FileAccess.Write, myIsolatedStorage))
                            {
                                int mediaFileLength = (int)e.Result.Length;
                                byte[] byteFile = new byte[mediaFileLength];
                                e.Result.Read(byteFile, 0, byteFile.Length);
                                fileStream.Write(byteFile, 0, byteFile.Length); 

                                // If there's something left, download it recursively
                                if (byteFile.Length > delta)
                                {
                                    iterator = iterator + delta + 1;

                                    headers = new WebHeaderCollection();
                                    headers[HttpRequestHeader.Range] = "bytes=" + iterator.ToString() + '-' + (iterator + delta).ToString();
                                    webClientReadCompleted.Headers = headers;
                                    webClientReadCompleted.OpenReadCompleted += downloadedSong_OpenReadCompleted;
                                    webClientReadCompleted.OpenReadAsync(new Uri(song.Link));
                                }
                            }
                        }
                    }
                }
            }

Answer 1:

要下载一个文件块,你需要进行多次请求。 为每个块。
可惜这不是可以说“让我这个文件,并在大小为X的块归还”;

假设服务器支持的话,你可以使用HTTP Range头到指定字节的文件服务器应该在响应请求返回。
然后,进行多个请求,以获得碎片文件,然后把它全部重新走到一起的设备上。 你可能会发现它最简单的进行顺序呼叫,并开始下一个一旦你已经得到了验证和以前的块。

这种方法使得当用户返回到应用程序简单,以恢复下载。 你只要看看有多少是以前下载,然后获得一个块。

我写这将下载的电影(高达2.6GB)的64K块的应用程序,然后打他们回来从IsolatedStorage与MediaPlayerLauncher 。 通过播放MediaElement应该工作太多,但我还没有证实。 您可以通过加载一个大文件直接到IsolatedStorage(通过独立存储资源管理器或类似)测试这一点,并检查打这样的记忆的影响。



Answer 2:

确认:您可以使用BackgroundTransferRequest下载多GB的文件,但你必须设置TransferPreferencesNone以强制下载,同时连接到外部电源的情况发生,并在连接到Wi-Fi,否则BackgroundTransferRequest将失败。


我不知道是否有可能使用BackgroundTransferRequest轻松下载大型文件,并让有关实施细则电话忧? 该文件似乎表明,文件下载超过100 MB是可能的,“范围”动词保留它自己的使用,所以如果可以在幕后它可能使用这个自动。

从关于超过100 MB的文件的文件:

对于大于100 MB的文件,必须设置转移到无或传送失败的TransferPreferences财产。 如果你不知道传输的大小,这是可能的,它可能会超过这个限制,您应该将该值设置为无,这意味着转移,才能继续当手机连接到外接电源,拥有的Wi-Fi连接。

从关于使用“范围”动词的文档:

所述BackgroundTransferRequest对象的标题属性被用于设置HTTP标头的传送请求。 下面的标题是保留给系统使用,不能调用应用程序使用。 加入以下标头至头集合中的一个会造成当添加(BackgroundTransferRequest)方法用于排队转移请求被抛出NotSupportedException异常:

  • 如果-Modified-Since的
  • 如果 - 无 - 匹配
  • 如果量程
  • 范围
  • 除非-Modified-Since的

这里的文档: http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh202955(v=vs.105).aspx



文章来源: Download file in chunks (Windows Phone)