如何使用Windows.Web.Http中的新HttpClient下载图像?

13

如何使用Windows.Web.Http.HttpClient下载图像?我想使用这个HttpClient,因为它可以在可移植类库中使用。


请记住,现在您将无法从Image控件提供的自动图像缓存中受益。 - Decade Moon
@DecadeMoon 是否可以直接指向 Web 上的 Uri?当上述 Uri 被设置时,我会收到无效 Uri 的错误(与下面使用的相同 Uri!)。图片将只是空白,但如果我添加了图像加载失败事件并查看异常,我可以看到该错误... 我也读了一些文章,说明这是不可能的,但也许只是没有解决问题... - David Spence
通常情况下,您只需直接指向Uri即可。很奇怪图片没有加载。您尝试过不同的图像URI吗?异常信息是什么? - Decade Moon
@DecadeMoon 我找到了我的实际问题所在... 当URI被设置为图像的源时,它似乎非常严格地进行转义,这是HttpClient没有抱怨的,所以也许它在转义方面稍微聪明一些... - David Spence
6个回答

13

这是我最终想到的做法。关于Windows.Web.Http.HttpClient并没有太多文档,很多在线示例使用的是像ReadAllBytesAsync这样的旧机制,而这个HttpClient并不支持。

值得一提的是,来自MSDN的这个问题给了我很大的帮助,所以感谢那个人。正如那里的评论所说,这个家伙一定是世界上唯一知道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;
    }
}

您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Rico Suter
2
@Jeroen Vannevel 不是最好的建议 -> https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/ - Morpheus
1
@JeroenVannevel 不应该处理 HttpClient,而是应该重复使用它: "HttpClient 应在应用程序的整个生命周期内实例化一次并重复使用。特别是在服务器应用程序中,为每个请求创建一个新的 HttpClient 实例将会在重负载下耗尽可用的套接字数量。这将导致 SocketException 错误。" 参见 https://learn.microsoft.com/en-us/aspnet/web-api/overview/advanced/calling-a-web-api-from-a-net-client 和 https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/ - Dan Diplo
@DanDiplo 是的,绝对正确。我写下那条评论已经有一段时间了,现在我更清楚了。我会删除它,以免引起混淆。对于未来的访问者:不要丢弃httpclient。 - Jeroen Vannevel
在ASP.Net Core中如何获取Windows.Web.Http的依赖项? - LatentDenis

7
在 .net core web api 中,您可以使用以下代码。
[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);
        }
    }

这里的GetProductImageQueryParam是一个包含输入参数的类。


4

这里的大多数答案都是正确的,但如果您需要简单的东西:

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
}

4
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;
            }
        }
}

6
你应该使用 await client.GetAsync(url) 而不是 client.GetAsync(url).Result。除此之外,很好的示例。 - Alisson Reinaldo Silva

0

已更新至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;
    }

0
制作了一个演示UWP应用程序,用于下载图像文件。 只需粘贴图像URL链接并按下载按钮即可。

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());
            }
        }
    }
}

您可以在这个文件夹中找到图片。

Users/[当前用户名]/AppData/Local/Packages/[应用程序包名]/LocalState/Images


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接