很长的json响应停止并发送HTTP标头作为文本然后继续

时间:2011-09-21 17:26:49

标签: php ajax json http http-headers

我完全迷失了这个问题。

我有一个获取json响应的ajax查询。查询在大多数情况下都能正常工作,但是当json响应非常大时,它似乎会发生绊倒。

问题是答案最终会以下列形式出现:

...est":"test length"}]]}
HTTP/1.1 200 OK
Date: Wed, 21 Sep 2011 17:10:32 GMT
Server: Apache/2.2.11 (Win32) mod_ssl/2.2.11 OpenSSL/0.9.8k PHP/5.3.0
X-Powered-By: PHP/5.3.0
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Keep-Alive: timeout=5, max=90
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/html

5b03d
{"ResultsInfo":{"RequestID":"131661886010","FeedCompletion":{"0":"100"}},"ResultsData":[[{"test":"test length"},{"test":"test length"},

...0

...表示更多相同的“{”test“:”test length“},”string

所以响应似乎是以下形式:

  • 数据的最后部分
  • 身体打印出来的http响应标题
  • 字符'5b03d'
  • 数据的第一部分
  • 字符'0'

没有确切的响应时间,但是在360791个字符处却没有,但不是372797个字符。

我正在使用Yii PHP框架,但搜索范围很广,在论坛上没有看到任何内容。

在我看来,网络服务器正在将响应分成几个部分,或者超时并重新开始。

或者可能有最大回报?

修改 _ __ _ __ _ __ _ __ _ __ _ __ _ __ _ __ _ __ _ __ _ __ _ ___

我已按照建议尝试了应用程序/ json内容类型,但它仍在发生。正文中返回的标题的Tes文本部分如下(使用applciaiton / json编码时):

HTTP/1.1 200 OK
Date: Thu, 22 Sep 2011 08:48:28 GMT
Server: Apache/2.2.11 (Win32) mod_ssl/2.2.11 OpenSSL/0.9.8k PHP/5.3.0
X-Powered-By: PHP/5.3.0
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Keep-Alive: timeout=5, max=89
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/json

如何关闭此特定脚本的分块编码?

**编辑2_ _ __ _ __ _ __ _ __ _ __ _ __ _ __ _ __ _ __ _ __ _ _

我现在已经为我的标题添加了一个内容长度,我得到的响应标题仍然在正文中打印出来:

HTTP/1.1 200 OK
Date: Thu, 22 Sep 2011 11:55:39 GMT
Server: Apache/2.2.11 (Win32) mod_ssl/2.2.11 OpenSSL/0.9.8k PHP/5.3.0
X-Powered-By: PHP/5.3.0
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Content-Length: 372797
Keep-Alive: timeout=5, max=90
Connection: Keep-Alive
Content-Type: application/json

所以看起来它不再像chunked那样被发送了。但是存在同样的问题 - 响应具有内容,然后打印出标题然后更多内容。

**现在唯一的区别是它在响应中没有'5b03d'或'0'字符。

EDIT_3_的 _ __ _ __ _ __ _ __ _ __ _ __ _ __ _ __ _ _

这里要求的是我的PHP代码摘要

$dataArray = array(
    'ResultsData'=>array(
          array('test'=>'test length'),
          array('test'=>'test length'),
          array('test'=>'test length'),
          ...
));

$return = json_encode($dataArray);

header('Content-Length: '.strlen($return)); 
header('Content-type: application/json');

echo $return;

4 个答案:

答案 0 :(得分:2)

您在这里看到的是分块传输编码 - http://en.wikipedia.org/wiki/Chunked_transfer_encoding

这会导致与内容类型为text / html结合的问题。将内容类型设置为application / json应该可以解决问题。

答案 1 :(得分:2)

我有一个用json代码响应的Java服务器,给我你似乎描述的腐败。当返回的json变大时,文本被破坏。不同的浏览器显示不同的损坏,但相同的浏览器经常在相同的地方腐败。

在我的一个测试中,我发送了9492个字节。虽然Wireshark分析显示了tcp流中的字节,但是第一个1495是好的,接下来的5204都没有了。然后接下来的1495个字节安全到达,而下一个1298则丢失了。

这些数字就是一个例子。其他浏览器会针对同一发送呈现不同的损坏。相同的浏览器可能会重复几乎相同的数字。例如,第一次腐败几乎总是在Chrome的同一个字节上。

json数量限制为总是成功的4000字节。

我还没有找到通过在此上下文中设置内容长度来停止chunkin的方法。只是为了让您了解代码的可信度:同样的Javaserver已经为浏览器提供了超过12年的html而没有损坏。但是Json响应是由outputstream发送的,而我没有设置标题。

我认为当我从自己的java程序发送时,标头由apache服务器组成。

答案 2 :(得分:1)

我没有找到这个问题的答案,但是已经解决了这个问题。

在标准的php文件中,我写了这段代码:

<?php

// Make a large array of strings
for($i=0;$i<10000;$i++)
{        
  $arr[] = "testing this string becuase it is must longer than all the rest to see if we can replicate the problem. testing this string becuase it is must longer than all the rest to see if we can replicate the problem. testing this string becuase it is must longer than all the rest to see if we can replicate the problem.";
}

// Create one large string from array
$var = implode("-",$arr);

// Set HTTP headers to ensure we are not 'chunking' response
header('Content-Length: '.strlen($var)); 
header('Content-type: text/html');

// Print response
echo $var;

?>

并在浏览器中访问它并遇到了同样的问题。

其他人可以为我试试这个吗?(我现在试过两台电脑同样的结果)

答案 3 :(得分:0)

我从来没有问过发送chunked Json。但..

正确的内容将被分块,因为内容长度是未知的,而PHP回应这个和客户端。

  1. ob_start()... ob_end_flush()确保一次发送内容,并自动设置content-lenth标题。

  2. 压缩数据永远不会被分块。所以: ob_start(ob_gzhandler)... ob_end_flush()有效。

  3. 在客户端脚本中测试你的json。

  4. 重复'测试'无用。嵌套有限制。

  5. dataArray = array('ResultsData'=&gt; array(length0,length1,length2,...));

    echo json_encode($ dataArray,JSON_NUMERIC_CHECK);

    JSON_NUMERIC_CHECK从数字中删除引号。

    1. ?5b03d?你试图发送二进制字符串吗?

    2. 我认为内容长度为373kb远远没有内存溢出?