DownloadString和HttpWebResponse没有返回完整的JSON内容

时间:2014-07-07 15:03:18

标签: c# .net httpwebrequest webclient httpwebresponse

我正在尝试将以下url中的JSON响应存储在字符串中。大多数情况下,我运行代码,JSON响应的最后几个字符被切断。当您在浏览器中访问该URL时,将显示完整的JSON响应。有时我的代码有效,但大多数情况下它返回部分内容。

如果我减少了我请求的网址中查询的长度,我会收到更多内容,更接近完整响应,这很奇怪。如果我完全删除查询字符串,通常会返回完整的JSON响应。问题是我想保持查询字符串不变。

我尝试了各种替代方案,包括更改编码,使用HttpWebRequest / HttpWebResponse,copying the response into a MemoryStream,使用byte bufferchanging the protocol version读取响应等。

有关如何获得完整回复并能解释发生了什么的任何想法?谢谢!

System.Net.WebClient wc = new System.Net.WebClient();            
string data = wc.DownloadString("http://static.arcgis.com/attribution/World_Topo_Map?f=json&callback=dojo.io.script.jsonp_dojoIoScript19._jsonpCallback");
Console.Write(data);// String should end with ",-119.2]}]}]});"
Console.Read();

3 个答案:

答案 0 :(得分:7)

这是一个服务器问题,但我很幸运,我相信有一个解决方法。服务器未返回正确的未压缩结果。如果您更改客户端代码以接受压缩响应,则问题似乎消失了。

为什么未压缩的响应被破坏了。服务器可能遇到64K以上的响应问题(这个json是64.8K)。可能的是,服务器的长度计算中存在一个错误,该错误仅在某些情况下或某些地图中显示。我不确定。因此,无法保证压缩变通方法在所有情况下都能正常工作,我建议您进行测试。并跟进ArcGIS人员,以便他们了解此错误。

这里是我要返回正确JSON的解压缩代码(改编自https://stackoverflow.com/a/4567408/126352)。

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

GZipWebClient wc = new GZipWebClient();
string data = wc.DownloadString("http://static.arcgis.com/attribution/World_Topo_Map?f=json&callback=dojo.io.script.jsonp_dojoIoScript19._jsonpCallback");

以下是我发现此解决方法的方法:

  • 首先我在代码
  • 中重现了这个问题
  • 然后我将请求更改为HTTP 1.0(没有chunked encoding或压缩)并注意到服务器返回的Content-Length标头是66338。但实际内容比这长。因此服务器告诉客户端内容比实际更短,这就解释了为什么WebClient响应被截断了。
  • 然后我尝试用客户端手动处理分块编码,但这没有用 - 我得到了相同的截断。
  • 那时我想知道这是一个绝对长度问题,例如服务器处理的响应时间较短,但低估了较长响应的长度。
  • 所以我使用Fiddler来处理请求标头,我发现删除压缩标头(Accept-Encoding:gzip,deflate,sdch)会重现问题。
  • 这解释了为什么此请求在浏览器(使用压缩)中有效但在代码中无效。
  • 所以我尝试了一个压缩感知的C#客户端,一切正常!

不幸的是,这并没有告诉您根本原因,因此压缩变通方法在所有情况下都可能起作用,也可能不起作用。它可能会在更长的响应中中断。它可能会在不同的地图上破裂。测试它以确保!

它也没有解释为什么@ssut无法复制。可能只有ArgGIS集群中的某些服务器容易受到攻击?我不知道。

顺便说一句,如果您想向NSGIS报告错误,可以使用这些HTTP请求来重现问题:

GET http://static.arcgis.com/attribution/World_Topo_Map?f=json&callback=dojo.io.script.jsonp_dojoIoScript19._jsonpCallback HTTP/1.0
Accept: text/html, application/xhtml+xml, */*
Accept-Language: en-US
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
Host: static.arcgis.com

答案 1 :(得分:0)

我使用您的代码进行测试,此代码运行正常。

P.S。当你用于解析json时,你不需要&callback参数。 (回调参数需要在javascript上进行jsonp回调)

答案 2 :(得分:0)

得出答案,因为我没有足够的声誉对你的答案发表评论......

我认为这是客户端的单声道错误,而不是服务器错误。我一直在用我正在使用的一些代码中跟踪这个问题。它在Windows上使用.Net完美运行。它只在使用mono运行代码时失败。当我使用你的GZipWebClient时,它也可以在单声道上完美运行。