1

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?

Fraga
  • 1,361
  • 2
  • 15
  • 47

3 Answers3

4

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.GZip | DecompressionMethods.Deflate });

    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");
        client.DefaultRequestHeaders.AcceptEncoding.ParseAdd("gzip, deflate");
        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

aepot
  • 4,558
  • 2
  • 12
  • 24
  • My I know where or how did you figure out it was this string? text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 ??? – Fraga Feb 06 '21 at 05:33
  • @Fraga copied from Network log (dev tools) in my Firefox Browser. Probably this string can be shortened or changed ([docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept)). – aepot Feb 06 '21 at 10:42
1

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

halfer
  • 19,824
  • 17
  • 99
  • 186
TheGeneral
  • 79,002
  • 9
  • 103
  • 141
  • This works too!.. but the solution above by aepot is easier! My problem was the header, its amazing to learn something new! thanks. – Fraga Feb 06 '21 at 05:27
  • Just interesting, where do you setup `HttpClientHandler.AutomaticDecompression`? Does factory create the client with enabled one by default? – aepot Feb 06 '21 at 11:39
  • 1
    @aepot good point, i forgot to add ConfigurePrimaryHttpMessageHandler to the builder :o – TheGeneral Feb 07 '21 at 22:49
0

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.

NineBerry
  • 26,306
  • 3
  • 62
  • 93
  • No, I did tried that! and it fails anyway!.. not the first time! but the subsequent calls https://aplweb.soriana.com/foto/fotolib//99/7503019554999/7503019554999-01-01-01.jpg https://aplweb.soriana.com/foto/fotolib//99/7503001566399/7503001566399-01-01-01.jpg https://aplweb.soriana.com/foto/fotolib//99/7502246460899/7502246460899-01-01-01.jpg https://aplweb.soriana.com/foto/fotolib//99/0787359175299/0787359175299-01-01-01.jpg https://aplweb.soriana.com/foto/fotolib//99/0077661134399/0077661134399-01-01-01.jpg – Fraga Feb 06 '21 at 05:24