1

This is the most bizarre thing.

I'm trying to download this file using the C# HttpClient: https://statics.teams.microsoft.com/evergreen-assets/skype/v2/smile/50.png

It happens to be one of the Microsoft Teams emoticon image files.

smiley.png

(Incidentally, I had to download this image locally to my machine with Chrome, then upload it from there, as the StackOverflow image upload couldn't handle the URL either...)

I've tried a number of different cracks at the code to download this file - the most straightforward and usual way of doing so, stripped down to essentials, is:

var client = new HttpClient();
var webStream = await client.GetStreamAsync("https://statics.teams.microsoft.com/evergreen-assets/skype/v2/smile/50.png");
using (var fileStream = new FileStream("smilely.png", FileMode.OpenOrCreate)) {
    webStream.CopyTo(fileStream);
}

I've tried several different ways using HttpClient, using the System.Net.WebClient, and raw WebRequests as well, with the same results.

If I put the URL into my browser and go to it, I see the image as expected, but if I am downloading the file from C#, I get a corrupted image that won't open.

The proper file, downloaded using the browser is 2127 bytes, starting with the proper PNG header bytes, like so:

89 50 4E 47 0D 0A 1A 0A

The file that I download programmatically is screwed up, with an entirely different byte stream, which is only 2093 bytes, and starts:

1F 8B 08 00 00 00 00 00

I don't have this problem downloading other emoticon images from the same set, like https://statics.teams.microsoft.com/evergreen-assets/skype/v2/laugh/50.png

enter image description here

What in the world could possibly be going on with this?

EricRRichards
  • 474
  • 7
  • 20
  • 2
    `1F 8B` is the [magic number](https://en.wikipedia.org/wiki/List_of_file_signatures) for GZIP. – canton7 Oct 23 '19 at 19:06

1 Answers1

2

1F 8B is the magic number for GZIP.

If we look at the response content headers with:

var client = new HttpClient();
var response = await client.GetAsync("https://statics.teams.microsoft.com/evergreen-assets/skype/v2/smile/50.png");
var contentHeaders = response.Content.Headers;

We can see that ContentEncoding is gzip.

So it looks like something's up with the server configuration. Normally a server will only give you something with content-encoding if you explicitly state that you accept encoded responses with the Accept-Encoding header, but it looks like this particular server isn't playing by the rules for this file.

Your browser did say that it accepted gzip-encoded files, so doesn't blink when it gets a gzip-encoded response. Your C# code wasn't expecting that.

You can get HttpClient to automatically decompress gzip-encoded content with:

var handler = new HttpClientHandler()
{
    AutomaticDecompression = System.Net.DecompressionMethods.GZip
};
var client = new HttpClient(handler);
canton7
  • 37,633
  • 3
  • 64
  • 77
  • Thank you very much, I've been beating my head on this all day. – EricRRichards Oct 23 '19 at 19:24
  • 1
    @Eric No problem! It's well worth knowing that magic numbers are a thing, for problems like this. The `file` utility is also great at trying to guess what format a file is in - it figures that this is gzip straight away. – canton7 Oct 23 '19 at 19:30
  • 1
    @Eric But, if you got the full response and poked around in its properties, you'd probably have spotted the `gzip` pop up, which would have been a clue. One of the secrets to debugging is just to keep trying things! – canton7 Oct 23 '19 at 19:31