【问题标题】:DownloadString and HttpWebResponse is not returning the full JSON contentDownloadString 和 HttpWebResponse 未返回完整的 JSON 内容
【发布时间】:2014-07-07 15:03:18
【问题描述】:

我正在尝试将来自以下 url 的 JSON 响应存储在字符串中。大多数时候我运行代码,JSON 响应的最后几个字符被截断。当您在浏览器中访问 url 时,会显示完整的 JSON 响应。有时我的代码可以工作,但大多数时候它会返回部分内容。

如果我在我请求的 url 中减少查询字符串的长度,我会得到更多的内容并更接近完整的响应,这很奇怪。如果我完全删除查询字符串,通常会返回完整的 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();

【问题讨论】:

    标签: c# .net httpwebrequest webclient httpwebresponse


    【解决方案1】:

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

    不清楚的是为什么未压缩的响应会被破坏。服务器可能无法处理超过 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 集群中的某些服务器易受攻击?我不知道。

    顺便说一句,如果您想向 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
    

    【讨论】:

    • 这是一个很棒的答案!我验证了压缩解决方法有效!感谢您的帮助!
    【解决方案2】:

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

    附言当您仅用于解析 json 时,您不需要 &callback 参数。 (javascript上jsonp回调需要回调参数)

    【讨论】:

    • 谢谢,我正在处理的代码库需要传递回调参数。可能有办法解决这个问题,所以我不会排除这一点。
    • 如何在 mac 上运行 C#
    • @Gupta 我使用了Mono Project 和 Xamarin Studio。如果在你的 Mac 上安装了 homebrew,你可以使用 brew install mono 安装单声道
    • @Nice,我在 Windows 上 :)
    【解决方案3】:

    留下一个答案,因为我没有足够的声誉对你的答案发表评论......

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

    【讨论】:

      猜你喜欢
      • 2013-11-03
      • 2015-07-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-26
      • 1970-01-01
      • 2012-06-02
      • 2020-11-24
      相关资源
      最近更新 更多