Pobierz plik w kawałkach (Windows Phone)

W mojej aplikacji mogę pobrać niektóre pliki multimedialne z Internetu. Normalnie użyłemWebClient.OpenReadCompleted metoda pobierania, deszyfrowania i zapisywania pliku do IsolatedStorage. Działało dobrze i wyglądało tak:

 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
                 }
           }

Ale po pewnym dochodzeniu dowiedziałem się, że przy dużych plikach (dla mnie to ponad 100 MB) dostajęBrak pamięci wyjątek podczas pobierania tego pliku. Przypuszczam, że to dlatego, że WebClient.OpenReadCompleted ładuje cały strumień do RAM i dławików ... I będę potrzebował więcej pamięci do odszyfrowania tego strumienia.

Po kolejnym badaniu odkryłem, jak podzielić duży plik na porcje po zdarzeniu OpenReadCompleted podczas zapisywania tego pliku do IsolatedStorage (lub deszyfrowania, a następnie zapisywania w moim czasie), ale to pomogłoby tylko w części problemu ... Podstawowa rzecz w tymjak zapobiec dławieniu telefonu podczas procesu pobierania. Czy istnieje sposób na pobranie dużego pliku w kawałkach? Wtedy mógłbym użyć znalezionego rozwiązania, aby przejść przez proces deszyfrowania. (i wciąż musiałbym znaleźć sposób na załadowanie tak dużego pliku do mediaElement, ale to byłoby kolejne pytanie)

Odpowiedź:

 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));
                                }
                            }
                        }
                    }
                }
            }

questionAnswers(2)

yourAnswerToTheQuestion