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

Jam*_*ruk 2 .net c# webclient httpwebrequest httpwebresponse

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

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

我尝试了各种替代方法,包括更改编码,使用HttpWebRequest/HttpWebResponse,将响应复制到MemoryStream,使用字节缓冲区读取响应,更改协议版本等.

关于如何获得完整响应并能解释发生了什么的任何想法?谢谢!

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();
Run Code Online (Sandbox Code Playgroud)

Jus*_*ant 7

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

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

这是我要返回正确的JSON 的解压缩代码(改编自/sf/answers/319718591/).

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");
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

顺便说一句,如果你想将错误报告给ArcGIS,这里有一个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
Run Code Online (Sandbox Code Playgroud)