我正在构建一个WP8应用程序,它在后台任务中使用HttpClient下载图像。我的问题是,无论我等待多长时间完成,都不会下载一些图像。图像大小最大为几兆字节。
我用来下载图片的代码:
internal static async Task<bool> Download_Wallpaper(string image_url, string file_name, string destination_folder_name)
{
try
{
using (var client = new HttpClient())
{
// 12MB max images
client.Timeout = TimeSpan.FromSeconds(5);
client.MaxResponseContentBufferSize = DeviceStatus.ApplicationMemoryUsageLimit / 2;
//client.Timeout = TimeSpan.FromSeconds(5);
byte[] image_byte_arr;
try
{
/* var requestMessage = new HttpRequestMessage( HttpMethod.Get, image_url );
var responseMessage = await client.SendAsync((requestMessage));
// byte array of image
image_byte_arr = await responseMessage.Content.ReadAsByteArrayAsync();
*/
// byte array of image
image_byte_arr = await client.GetByteArrayAsync(image_url);
}
// Could not download
catch (OutOfMemoryException X)
{
GC.Collect();
return false;
}
var folder = await StorageFolder.GetFolderFromPathAsync(destination_folder_name);
// Create file
StorageFile file = await folder.CreateFileAsync(file_name, CreationCollisionOption.ReplaceExisting);
using (var write_stream = await file.OpenStreamForWriteAsync())
{
write_stream.Write(image_byte_arr, 0, image_byte_arr.Length);
}
Console.WriteLine(DeviceStatus.ApplicationCurrentMemoryUsage);
return true;
}
}
catch (HttpRequestException X)
{
Console.WriteLine(X);
return false;
}
catch (OutOfMemoryException X)
{
GC.Collect();
return false;
}
catch (Exception X)
{
Console.WriteLine(X);
return false;
}
}
这是无法下载的示例图片:https://upload.wikimedia.org/wikipedia/commons/9/95/Tracy_Caldwell_Dyson_in_Cupola_ISS.jpg
根据我的经验,由于某种原因,所有维基媒体图像都无法下载。
我认为无法使用HttpClient跟踪下载进度。有办法吗?
编辑:设置超时似乎没有任何功能。 5秒后不会抛出HttpRequestException。
编辑2:我尝试了一种不同的方法,即anonshankar建议的方法。使用该方法,代码将卡在该行:
byte[] img = response.Content.ReadAsByteArrayAsync();
所以HttpResponse到了,但不管怎么说,无论我给它多少时间,都无法读出字节。 这怎么可能发生?困难的部分是获得响应,读取字节应该很简单。
同样,这只发生在一些图像上,大多数都是正确下载的。上面提到了一个例子。
我修改了我的图片下载程序代码,以便在几秒钟后超时。这是我的最终代码:
internal static async Task<bool> Download_Wallpaper(string image_url, string file_name, string destination_folder_name)
{
try
{
using (var client = new HttpClient())
{
// prevent running out of memory
client.MaxResponseContentBufferSize = DeviceStatus.ApplicationMemoryUsageLimit / 3;
byte[] image_byte_arr = null;
using (CancellationTokenSource cts = new CancellationTokenSource())
{
var task = Task.Factory.StartNew(() =>
{
try
{
image_byte_arr = client.GetByteArrayAsync(image_url).Result;
}
catch (AggregateException X)// Handling read errors, usually image is too big
{
Console.WriteLine(X.Message);
foreach (var v in X.InnerExceptions)
Console.WriteLine(v.Message);
image_byte_arr = null;
}
}, cts.Token);
bool finished_in_time = task.Wait(TimeSpan.FromSeconds(5));
if (!finished_in_time)// Timeout
{
cts.Cancel();
task.Wait();
return false;
}
else if (image_byte_arr == null)// Read error
{
return false;
}
}
var folder = await StorageFolder.GetFolderFromPathAsync(destination_folder_name);
// Create file
StorageFile file = await folder.CreateFileAsync(file_name, CreationCollisionOption.ReplaceExisting);
using (var write_stream = await file.OpenStreamForWriteAsync())
{
write_stream.Write(image_byte_arr, 0, image_byte_arr.Length);
}
Console.WriteLine(DeviceStatus.ApplicationCurrentMemoryUsage);
return true;
}
}
catch (HttpRequestException X)
{
Console.WriteLine(X);
return false;
}
catch (OutOfMemoryException X)
{
GC.Collect();
return false;
}
catch (Exception X)
{
Console.WriteLine(X);
return false;
}
}
欢迎任何改进建议,我仍然不明白为什么方法 HttpContent.ReadAsByteArrayAsync()被卡住了。
答案 0 :(得分:0)
试试这个适用于我的snippet
。
HttpClient client = new HttpClient();
HttpResponseMessage response = await client.GetAsync("give the url");
byte[] img = response.Content.ReadAsByteArray();
InMemoryRandomAccessStream randomAccessStream = new InMemoryRandomAccessStream();
DataWriter writer = new DataWriter(randomAccessStream.GetOutputStreamAt(0));
writer.WriteBytes(img);
await writer.StoreAsync();
BitmapImage b = new BitmapImage();
b.SetSource(randomAccessStream);
pic.Source = b; //(pic is an `<Image>` defined in the `XAML`
希望它有所帮助!