在Silverlight中我们可以通过设置HttpWebRequest.AllowReadStreamBuffering为false,或者使用HttpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead)来实现在回调函数中不必等到Stream完全下载完成后才能读取数据,以便计算下载速度或进行其他处理。然而在WPRT应用中(WinRT未受影响)这两种方式都失去了效果,见示例:
string url = "http://abc";
HttpWebRequest hwr = (HttpWebRequest)HttpWebRequest.Create(new Uri(url));
hwr.AllowReadStreamBuffering = false;
hwr.BeginGetResponse(GetFileCallback, hwr);
private async void GetFileCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)(asynchronousResult.AsyncState);
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
StorageFolder tempFolder = await ApplicationData.Current.LocalFolder.CreateFolderAsync("temp", CreationCollisionOption.OpenIfExists);
StorageFile tempFlvFile = await tempFolder.CreateFileAsync("file.tmp ", CreationCollisionOption.ReplaceExisting);
using (Stream streamResponse = response.GetResponseStream())
{
using (Stream fileStream = await tempFile.OpenStreamForWriteAsync())
{
Debug.WriteLine("file length: " + response.ContentLength);
byte[] bs = new byte[1024 * 1024];
int size = streamResponse.Read(bs, 0, bs.Length); // streamResponse被完全下载之前不返回; SL8.0和WinRT未受影响
while (size >= 0)
{
// loop logical
}
}
}
}
HttpWebRequest hwr = (HttpWebRequest)HttpWebRequest.Create(new Uri(url));
hwr.AllowReadStreamBuffering = false;
hwr.BeginGetResponse(GetFileCallback, hwr);
private async void GetFileCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)(asynchronousResult.AsyncState);
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
StorageFolder tempFolder = await ApplicationData.Current.LocalFolder.CreateFolderAsync("temp", CreationCollisionOption.OpenIfExists);
StorageFile tempFlvFile = await tempFolder.CreateFileAsync("file.tmp ", CreationCollisionOption.ReplaceExisting);
using (Stream streamResponse = response.GetResponseStream())
{
using (Stream fileStream = await tempFile.OpenStreamForWriteAsync())
{
Debug.WriteLine("file length: " + response.ContentLength);
byte[] bs = new byte[1024 * 1024];
int size = streamResponse.Read(bs, 0, bs.Length); // streamResponse被完全下载之前不返回; SL8.0和WinRT未受影响
while (size >= 0)
{
// loop logical
}
}
}
}
期望运行结果:
实际运行结果:
问题原因
通过和微软相关团队的沟通,得知这是一个已经确认的bug,不过暂时没有修复bug的预计时间。
解决方案
目前的替代方案是使用Windows.Web.Http.HttpClient:
HttpClient client = new HttpClient();
IInputStream stream = await client.GetInputStreamAsync(new Uri("http://video.ch9.ms/sessions/build/2014/2-517_LG.mp4"));
StorageFolder tempFolder = await ApplicationData.Current.LocalFolder.CreateFolderAsync("temp", CreationCollisionOption.OpenIfExists);
StorageFile tempFlvFile = await tempFolder.CreateFileAsync("file.tmp", CreationCollisionOption.ReplaceExisting);
using (Stream streamResponse = stream.AsStreamForRead())
{
Stopwatch newWatch = new Stopwatch();
newWatch.Start();
using (Stream streamFile = await tempFlvFile.OpenStreamForWriteAsync())
{
int bytesRead = 0;
byte[] myBuffer = new byte[1024 * 1024];
while ((bytesRead = streamResponse.Read(myBuffer, 0, myBuffer.Length)) >= 0)
{
Debug.WriteLine(bytesRead.ToString() + " bytes read. Elapsed time: " + newWatch.Elapsed.TotalSeconds.ToString("0.000") + " seconds");
streamFile.Write(myBuffer, 0, bytesRead);
}
}
}
IInputStream stream = await client.GetInputStreamAsync(new Uri("http://video.ch9.ms/sessions/build/2014/2-517_LG.mp4"));
StorageFolder tempFolder = await ApplicationData.Current.LocalFolder.CreateFolderAsync("temp", CreationCollisionOption.OpenIfExists);
StorageFile tempFlvFile = await tempFolder.CreateFileAsync("file.tmp", CreationCollisionOption.ReplaceExisting);
using (Stream streamResponse = stream.AsStreamForRead())
{
Stopwatch newWatch = new Stopwatch();
newWatch.Start();
using (Stream streamFile = await tempFlvFile.OpenStreamForWriteAsync())
{
int bytesRead = 0;
byte[] myBuffer = new byte[1024 * 1024];
while ((bytesRead = streamResponse.Read(myBuffer, 0, myBuffer.Length)) >= 0)
{
Debug.WriteLine(bytesRead.ToString() + " bytes read. Elapsed time: " + newWatch.Elapsed.TotalSeconds.ToString("0.000") + " seconds");
streamFile.Write(myBuffer, 0, bytesRead);
}
}
}
» 转载请注明来源及链接:未来代码研究所