How do I use the new HttpClient from Windows.Web.Http to download an image?
Asked Answered
S

6

13

Using Windows.Web.Http.HttpClient how can I download an image? I would like use this HttpClient because it is available to use in portable class libraries.

Struble answered 16/11, 2014 at 15:52 Comment(4)
Keep in mind that now you won't benefit from the automatic image caching that the Image control provides.Olaolaf
@DecadeMoon Is it possible to point to a Uri on the web directly? I was getting errors about the Uri being invalid when being set as above (the same Uri used below!). The image would just be blank but I could see that error if I added the image load failed event and had a look at the exception... I also read a few articles stating it wasn't possible, but maybe just didn't work it out...Struble
Yes, typically you'd just point to a Uri directly. That's weird that the image wasn't loading. Did you try different image URIs? What did the exception say?Olaolaf
@DecadeMoon I found out what my actual problem was here... when the URI is set as the source of an image, it seems it's very strict about escaping, something which HttpClient didn't complain about, so maybe it's slightly smarter with its escaping...Struble
S
13

This is what I eventually came up with. There is not much documentation around Windows.Web.Http.HttpClient and a lot of the examples online use old mechanisms like ReadAllBytesAsync which are not available with this HttpClient.

I should note that this question from MSDN helped me out a lot, so thanks to that person. As the comment over there states, this guy must be the only person in the world who knows about Windows.Web.Http!

using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Threading.Tasks;
using System.Windows.Media.Imaging;
using Windows.Storage.Streams;
using Windows.Web.Http;

public class ImageLoader
{
    public async static Task<BitmapImage> LoadImage(Uri uri)
    {
        BitmapImage bitmapImage = new BitmapImage();

        try
        {
            using (HttpClient client = new HttpClient())
            {
                using (var response = await client.GetAsync(uri))
                {
                    response.EnsureSuccessStatusCode();

                    using (IInputStream inputStream = await response.Content.ReadAsInputStreamAsync())
                    {
                        bitmapImage.SetSource(inputStream.AsStreamForRead());
                    }
                }
            }
            return bitmapImage;
        }
        catch (Exception ex)
        {
            Debug.WriteLine("Failed to load the image: {0}", ex.Message);
        }

        return null;
    }
}
Struble answered 16/11, 2014 at 15:59 Comment(5)
Just FYI: There is also a a SetSourceAsync method which may be better to avoid blocking the UIPursuit
@Jeroen Vannevel Not the best advise -> aspnetmonsters.com/2016/08/2016-08-27-httpclientwrongCriminate
@JeroenVannevel No, HttpClient should NOT be disposed of, but re-used: "HttpClient is intended to be instantiated once and re-used throughout the life of an application. Especially in server applications, creating a new HttpClient instance for every request will exhaust the number of sockets available under heavy loads. This will result in SocketException errors." See learn.microsoft.com/en-us/aspnet/web-api/overview/advanced/… and aspnetmonsters.com/2016/08/2016-08-27-httpclientwrongDomination
@DanDiplo yes, definitely true. It's been a while since I've written that comment and I know better now. I'll delete it so there's no confusion. For future visitors: don't dispose the httpclientFutrell
How do you get Windows.Web.Http dependencies in ASP.Net Core?Swarth
C
7

In .net core web api you can use the below code

[Route("getProductImage/v1")]
    [HttpGet]
    public async Task<IActionResult> getProductImage(GetProductImageQueryParam parammodel)
    {
        using (HttpClient client = new HttpClient())
        {
            MNimg_URL = MNimg_URL + parammodel.modelname;
            HttpResponseMessage response = await client.GetAsync(MNimg_URL);
            byte[] content = await response.Content.ReadAsByteArrayAsync();
            //return "data:image/png;base64," + Convert.ToBase64String(content);
            return File(content, "image/png", parammodel.modelname);
        }
    }

here GetProductImageQueryParam is a class with input parameters

Cilia answered 19/9, 2017 at 9:23 Comment(0)
H
5
public async void downLoadImage(string url)
{
        using (var client = new HttpClient())
        {
            var response = client.GetAsync(url).Result;
            BitmapImage bitmap = new BitmapImage();
            if (response != null && response.StatusCode == HttpStatusCode.OK)
            {
                using (var stream = await response.Content.ReadAsStreamAsync())
                {
                    using (var memStream = new MemoryStream())
                    {
                        await stream.CopyToAsync(memStream);
                        memStream.Position = 0;
                        bitmap.SetSource(memStream.AsRandomAccessStream());
                    }
                }
                HardcodedValues.profilePic = bitmap;
            }
        }
}
Hallette answered 6/1, 2017 at 14:9 Comment(1)
You should use await client.GetAsync(url) instead of client.GetAsync(url).Result. Other than that, nice example.Antiquarian
A
5

Most answers here are correct but if you need something simple:

HttpClient http = new HttpClient();

var res = await http.GetAsync(linktojpg);

byte[] bytes = await res.Content.ReadAsByteArrayAsync();

using (Image image = Image.FromStream(new MemoryStream(bytes)))
{
    image.Save(path/name.jpg);  // Or Png
}
Andalusia answered 15/11, 2022 at 14:28 Comment(0)
G
0

Updated for 8.1 - 10.

    public async static Task<BitmapImage> LoadImage(Uri uri)
    {
        BitmapImage bitmapImage = new BitmapImage();

        try
        {
            using (Windows.Web.Http.HttpClient client = new Windows.Web.Http.HttpClient())
            {
                using (var response = await client.GetAsync(uri))
                {
                    response.EnsureSuccessStatusCode();

                    using (MemoryStream inputStream = new MemoryStream())
                    {
                        await inputStream.CopyToAsync(inputStream);
                        bitmapImage.SetSource(inputStream.AsRandomAccessStream());
                    }
                }
            }
            return bitmapImage;
        }
        catch (Exception ex)
        {
            Debug.WriteLine("Failed to load the image: {0}", ex.Message);
        }

        return null;
    }
Gavra answered 12/1, 2016 at 1:29 Comment(0)
C
0

Made a demo UWP application for downloading an image file. Just paste the image URL link and press the download button.

MainPage.xaml

<Page
    x:Class="HttpDownloader.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:HttpDownloader"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <Grid>
        <StackPanel>
            <TextBox x:Name="uriInput"
                     Header="URI:" PlaceholderText="Please provide an uri"
                     Width="300"
                     HorizontalAlignment="Center"/>
            <Button Content="Dowload"
                    HorizontalAlignment="Center"
                    Click="Button_Click"/>
        </StackPanel>
    </Grid>
</Page>

MainPage.xaml.xs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using System.Net.Http;
using System.Net;
using Windows.Storage.Streams;
using Windows.Storage.Pickers;
using Windows.Storage;
using Windows.Graphics.Imaging;
using System.Threading;

// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409

namespace HttpDownloader
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
        }

        private async void Button_Click(object sender, RoutedEventArgs e)
        {
            HttpClient client = new HttpClient();
            string imageUrl = uriInput.Text;
            try
            {
                using (var cancellationTokenSource = new CancellationTokenSource(50000))
                {
                    var uri = new Uri(WebUtility.HtmlDecode(imageUrl));
                    using (var response = await client.GetAsync(uri, cancellationTokenSource.Token))
                    {
                        response.EnsureSuccessStatusCode();
                        var mediaType = response.Content.Headers.ContentType.MediaType;
                        string fileName = DateTime.Now.ToString("yyyyMMddhhmmss");
                        if (mediaType.IndexOf("jpg", StringComparison.OrdinalIgnoreCase) >= 0
                            || mediaType.IndexOf("jpeg", StringComparison.OrdinalIgnoreCase) >= 0)
                        {
                            fileName += ".jpg";
                        }
                        else if (mediaType.IndexOf("png", StringComparison.OrdinalIgnoreCase) >= 0)
                        {
                            fileName += ".png";
                        }
                        else if (mediaType.IndexOf("gif", StringComparison.OrdinalIgnoreCase) >= 0)
                        {
                            fileName += ".gif";
                        }
                        else if (mediaType.IndexOf("bmp", StringComparison.OrdinalIgnoreCase) >= 0)
                        {
                            fileName += ".bmp";
                        }
                        else
                        {
                            fileName += ".png";
                        }

                        // Get the app's local folder.
                        StorageFolder localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;

                        // Create a new subfolder in the current folder.
                        // Replace the folder if already exists.
                        string desiredName = "Images";
                        StorageFolder newFolder = await localFolder.CreateFolderAsync(desiredName, CreationCollisionOption.ReplaceExisting);
                        StorageFile newFile = await newFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);

                        using (Stream streamStream = await response.Content.ReadAsStreamAsync())
                        {
                            using (Stream streamToWriteTo = File.Open(newFile.Path, FileMode.Create))
                            {
                                await streamStream.CopyToAsync(streamToWriteTo);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception occur");
                Console.WriteLine(ex.ToString());
            }
        }
    }
}

You will find the image in this folder.

Users/[current user name]/AppData/Local/Packages/[Application package name]/LocalState/Images

Cuticula answered 18/1, 2023 at 7:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.