这里有一个奇怪的...我有以下 C# 代码:
static void Main(string[] args)
{
try
{
var url = "https://www.nordea.com/wemapp/api/fi/lists/currency/electronicExchangeFI.dat";
var result = DownloadData(url);
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
private static string DownloadData(string url)
{
var webClient = new WebClient();
byte[] xmlData = webClient.DownloadData(url);
webClient.Dispose();
string data = string.Empty;
if (xmlData.Length > 0)
{
data = System.Text.Encoding.Default.GetString(xmlData);
}
return data;
}
Run Code Online (Sandbox Code Playgroud)
使用这个特定的网站(一些汇率数据),上述作为 .NET Core/5 控制台应用程序失败,但它在 .NET Framework (4.7) 中按预期工作
在 .NET Core 中,我在方法上遇到以下异常webClient.DownloadData(url);-
WebClient 请求期间发生异常。
内部异常是
响应提前结束,预计至少有 1 个额外字节。
我也试过使用,new HttpClient().GetStringAsync(url).Result;但在 .NET Framework 和 .NET Core 中都失败了。
有没有人知道为什么会这样(它必须是带有 URL 的东西,但如何知道为什么以及在请求中更改什么)?
根据Fiddler 的说法,因为该服务器的响应违反了 HTTP 规范:
[ProtocolViolation] 内容长度不匹配:响应头指示 12,803 字节,但服务器发送了 12,802 字节。
.NET Framework 的 HTTP 堆栈因默默地容忍此类问题而臭名昭著,而 .NET Core 具有完全重写的堆栈,其宽容度要低得多。在这种情况下,Framework 似乎不是特别信任响应,Content-Length或者只是忽略它,而 Core 取决于它的正确性(我猜是为了性能优化)。
虽然有些人可能会争辩说 Core 的行为不太方便(尤其是因为没有办法选择退出它),但事实是,Framework 的宽大处理正是允许这种破坏行为传播并保持未修复的那种事情。Core 在这里做的是正确的事情,老实说,我很困惑运行该服务器的人如何设法搞砸了Content-Length这么简单的事情......而且他们显然从未测试过它是正确的......
您唯一的选择是联系服务器管理员并让他们修复他们的问题,或者使用较低级别的方法以绕过无效Content-Length. 下面给出了以下示例(不提供关于正确性或性能的保证;我测试过一次):
// https://docs.microsoft.com/dotnet/architecture/microservices/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests
var client = new HttpClient();
var responseStream = await client.GetStreamAsync("https://www.nordea.com/wemapp/api/fi/lists/currency/electronicExchangeFI.dat");
int bufferSize = 1024;
var streamBytes = new byte[0];
var buffer = new byte[bufferSize];
while (true)
{
var readCount = await responseStream.ReadAsync(buffer, 0, bufferSize);
var temp = new byte[streamBytes.Length + readCount];
Array.Copy(streamBytes, temp, streamBytes.Length);
Array.Copy(buffer, 0, temp, temp.Length - readCount, readCount);
streamBytes = temp;
if (readCount < buffer.Length)
break;
}
var responseText = Encoding.UTF8.GetString(streamBytes);
Console.WriteLine(responseText.Length); // 12802, the actual length
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
129 次 |
| 最近记录: |