【发布时间】:2013-01-14 03:52:36
【问题描述】:
在我的应用程序中,我可以从网络下载一些媒体文件。通常我使用 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 中并阻塞......而且我需要更多内存来解密这个流。
经过另一次调查,我发现如何在 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));
}
}
}
}
}
}
【问题讨论】:
-
你问过这个问题吗? stackoverflow.com/questions/14600426/…看看我的回复
-
@Hermit,不,我什至没有注意到那个,因为我最喜欢的标签中没有 windows-phone-8。不幸的是,你的回答对我没有帮助,理论上我知道,我应该怎么做:) 问题是“如何?”
-
不,那是文件传输系统,我无法控制文件传输。它应该是来自原生 WP7 类的一些方法,如 WebClient 或 httpwebrequest 或其他。
-
没有股票类/方法做你想做的事。如果你想使用夹头,你将不得不四处寻找解决方案。
标签: c# windows-phone-7 download chunking