WP8有些图像无法使用HttpClient下载

时间:2014-06-23 22:29:42

标签: windows-phone-8 dotnet-httpclient

我正在构建一个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()被卡住了。

1 个答案:

答案 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`

希望它有所帮助!