Fraga
Fraga

Reputation: 1451

Download .webp image from url with C#

I am trying to download an image from

http://aplweb.soriana.com/foto/fotolib/14/7503003936114/7503003936114-01-01-01.jpg

using WebClient.

When I browse the image in Chrome the image is there: enter image description here

The url ends in .jpg but the image is in .WEBP format.

    using (WebClient wb = new WebClient())
    {                  
         wb.DownloadFile("http://aplweb.soriana.com/foto/fotolib//14/7503003936114/7503003936114-01-01-01.jpg", "image.jpg");
    }

I have tried .DownloadData(), asyng methods, HttpClient, WebRequest directly... and I am always getting the same error.

enter image description here

Any idea?

Upvotes: 1

Views: 2871

Answers (3)

aepot
aepot

Reputation: 4824

Your code is fine but this is a server-specific behavior. Adding some request headers fixes the issue.

Here's an example using HttpClient

class Program
{
    private static readonly HttpClient client = new HttpClient(new HttpClientHandler()
    {
        AutomaticDecompression = DecompressionMethods.All // automatically adds HTTP header "Accept-Encoding: gzip, deflate, br"
    });

    static async Task Main(string[] args)
    {
        client.DefaultRequestHeaders.Accept.ParseAdd("text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
        try
        {
            Console.WriteLine("Downloading...");
            byte[] data = await client.GetByteArrayAsync("http://aplweb.soriana.com/foto/fotolib//14/7503003936114/7503003936114-01-01-01.jpg");
            Console.WriteLine("Saving...");
            File.WriteAllBytes("image.jpg", data);
            Console.WriteLine("OK.");
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

Console output

Downloading...
Saving...
OK.

Downloaded image

enter image description here

Upvotes: 5

TheGeneral
TheGeneral

Reputation: 81583

Your problem is to do with headers. But, let's start you on the right track and teach you one of the more modern ways of making Http Requests using DI, Services, and IHttpClientFactory.

Service

public class MyFunkyService
{
   private readonly IHttpClientFactory _clientFactory;

   public MyFunkyService(IHttpClientFactory clientFactory)
    => _clientFactory = clientFactory;

   public async Task<byte[]> GetSomeFunkyThingAsync()
   {
      using var client = _clientFactory.CreateClient();
      using var request = new HttpRequestMessage(HttpMethod.Get, "http://aplweb.soriana.com/foto/fotolib//14/7503003936114/7503003936114-01-01-01.jpg");

      request.Headers.Accept.ParseAdd("text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
      request.Headers.AcceptEncoding.ParseAdd("gzip, deflate");

      using var response = await client
         .SendAsync(request)
         .ConfigureAwait(false);

      response.EnsureSuccessStatusCode();

      return await response
         .Content
         .ReadAsByteArrayAsync()
         .ConfigureAwait(false);

   }
}

Set up

var provider = new ServiceCollection()
   .AddHttpClient()
   .AddSingleton<MyFunkyService>()
   .BuildServiceProvider();

Usage

// this would be injected 
var myClient = provider.GetRequiredService<MyFunkyService>();

var result = await myClient.GetSomeFunkyThingAsync();

Note : there are many many more variations on how you could do this. However at least you are not learning the old and busted ways of doing things

Upvotes: 1

NineBerry
NineBerry

Reputation: 28549

It seems that the server is only serving requests that support compression. WebClient doesn't support compression automatically. You can enable support for compression by inheriting your own class as described in this answer.

class MyWebClient : WebClient
{
    protected override WebRequest GetWebRequest(Uri address)
    {
        HttpWebRequest request = base.GetWebRequest(address) as HttpWebRequest;
        request.AutomaticDecompression =  DecompressionMethods.Deflate | DecompressionMethods.GZip;
        return request;
    }
}

Then use MyWebClient instead of WebClient.

Upvotes: 0

Related Questions