Olt*_*ter 6 c# download chunking windows-phone-7
在我的应用程序中,我可以从网上下载一些媒体文件.通常我使用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
}
}
Run Code Online (Sandbox Code Playgroud)
但经过一些调查后我发现有大文件(对我来说超过100 MB)我在下载此文件时遇到OutOfMemory异常.我想这是因为WebClient.OpenReadCompleted将整个流加载到RAM和chokes ......我需要更多的内存来解密这个流.
经过另一次调查,我发现在将OpenReadCompleted事件保存到IsolatedStorage(或解密然后保存在我的ocasion中)之后,如何将大文件分成块,但这只会导致一部分问题...问题是如何在下载过程中防止电话扼流圈.有没有办法以块的形式下载大文件?然后我可以使用找到的解决方案来通过解密过程.(而且我仍然需要找到一种方法将这样大的文件加载到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));
}
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
要分块下载文件,您需要发出多个请求。每个块一个。
不幸的是,不可能说“给我这个文件并以 X 大小的块返回它”;
假设服务器支持它,您可以使用 HTTPRange标头来指定服务器应返回文件的哪些字节以响应请求。
然后,您发出多个请求以将文件分成几部分,然后将其全部放回到设备上。您可能会发现最简单的方法是进行顺序调用,并在获得并验证前一个块后开始下一个调用。
这种方法使得当用户返回应用程序时恢复下载变得简单。您只需查看之前下载了多少内容,然后获取下一个块。
我编写了一个应用程序,它以 64K 块下载电影(最多 2.6GB),然后使用MediaPlayerLauncher. 通过 玩MediaElement应该也可以,但我还没有验证。您可以通过将大文件直接加载到IsolatedStorage(通过独立存储资源管理器或类似方式)来测试这一点,并检查以这种方式播放的内存影响。