使用 C# HttpClient 下载的 Skype 表情与使用浏览器下载的字节流不同
Skype Emoticon downloaded with C# HttpClient is a different byte stream than downloaded with browser
这是最奇怪的事情。
我正在尝试使用 C# HttpClient 下载此文件:
https://statics.teams.microsoft.com/evergreen-assets/skype/v2/smile/50.png
正好是Microsoft Teams表情图片文件之一
(顺便说一下,我不得不使用 Chrome 将这张图片本地下载到我的机器上,然后从那里上传它,因为 Whosebug 图片上传也无法处理 URL... )
我尝试了很多不同的破解代码来下载这个文件 - 最直接和最常用的方法是:
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);
}
我尝试了几种不同的方式使用 HttpClient,使用 System.Net.WebClient,以及原始 WebRequests,结果相同。
如果我将 URL 放入浏览器并转到它,我会按预期看到图像,但如果我从 C# 下载文件,我会得到一个无法打开的损坏图像。
使用浏览器下载的正确文件为 2127 字节,以正确的 PNG header 字节开头,如下所示:
89 50 4E 47 0D 0A 1A 0A
我以编程方式下载的文件搞砸了,具有完全不同的字节流,只有 2093 字节,并且开始于:
1F 8B 08 00 00 00 00 00
我从同一组下载其他表情图片没有这个问题,比如 https://statics.teams.microsoft.com/evergreen-assets/skype/v2/laugh/50.png
这到底是怎么回事?
1F 8B
是 GZIP 的 magic number。
如果我们查看响应内容 headers 有:
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;
我们可以看到ContentEncoding
是gzip
。
看来服务器配置出了问题。通常,如果您明确声明您接受带有 Accept-Encoding
header 的编码响应,服务器只会给您带有 content-encoding 的内容,但看起来这个特定的服务器不遵守规则对于这个文件。
您的浏览器确实表示它接受 gzip-encoded 文件,因此在收到 gzip-encoded 响应时不会闪烁。您的 C# 代码没有预料到这一点。
您可以获得 HttpClient
自动解压 gzip-encoded 内容:
var handler = new HttpClientHandler()
{
AutomaticDecompression = System.Net.DecompressionMethods.GZip
};
var client = new HttpClient(handler);
这是最奇怪的事情。
我正在尝试使用 C# HttpClient 下载此文件: https://statics.teams.microsoft.com/evergreen-assets/skype/v2/smile/50.png
正好是Microsoft Teams表情图片文件之一
(顺便说一下,我不得不使用 Chrome 将这张图片本地下载到我的机器上,然后从那里上传它,因为 Whosebug 图片上传也无法处理 URL... )
我尝试了很多不同的破解代码来下载这个文件 - 最直接和最常用的方法是:
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);
}
我尝试了几种不同的方式使用 HttpClient,使用 System.Net.WebClient,以及原始 WebRequests,结果相同。
如果我将 URL 放入浏览器并转到它,我会按预期看到图像,但如果我从 C# 下载文件,我会得到一个无法打开的损坏图像。
使用浏览器下载的正确文件为 2127 字节,以正确的 PNG header 字节开头,如下所示:
89 50 4E 47 0D 0A 1A 0A
我以编程方式下载的文件搞砸了,具有完全不同的字节流,只有 2093 字节,并且开始于:
1F 8B 08 00 00 00 00 00
我从同一组下载其他表情图片没有这个问题,比如 https://statics.teams.microsoft.com/evergreen-assets/skype/v2/laugh/50.png
这到底是怎么回事?
1F 8B
是 GZIP 的 magic number。
如果我们查看响应内容 headers 有:
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;
我们可以看到ContentEncoding
是gzip
。
看来服务器配置出了问题。通常,如果您明确声明您接受带有 Accept-Encoding
header 的编码响应,服务器只会给您带有 content-encoding 的内容,但看起来这个特定的服务器不遵守规则对于这个文件。
您的浏览器确实表示它接受 gzip-encoded 文件,因此在收到 gzip-encoded 响应时不会闪烁。您的 C# 代码没有预料到这一点。
您可以获得 HttpClient
自动解压 gzip-encoded 内容:
var handler = new HttpClientHandler()
{
AutomaticDecompression = System.Net.DecompressionMethods.GZip
};
var client = new HttpClient(handler);