我真的很感谢一些帮助理解这个Apache的行为。
我正在通过application / json中的iPhone Objective-C应用程序与PHP进行通信。 Gzip压缩在服务器上启用,并由客户端请求。
从我的.htaccess:
AddOutputFilterByType DEFLATE text/html text/plain text/xml application/x-httpd-php application/json
对于小的请求,Apache正在设置“Content-Length”标题。 例如(这些值是从头中的Objective-C中输出的):
Connection = "Keep-Alive"; "Content-Encoding" = gzip; "Content-Length" = 185; <------------- "Content-Type" = "application/json"; Date = "Wed, 22 Sep 2010 12:20:27 GMT"; "Keep-Alive" = "timeout=3, max=149"; Server = Apache; Vary = "Accept-Encoding"; "X-Powered-By" = "PHP/5.2.13"; "X-Uncompressed-Content-Length" = 217;
X-Uncompressed-Content-Length是我添加的一个头文件,设置为未压缩的JSONstring的大小。
正如你所看到的,这个请求非常小(217字节)。
以下是来自更大请求(282888字节)的标题:
Connection = "Keep-Alive"; "Content-Encoding" = gzip; "Content-Type" = "application/json"; Date = "Wed, 22 Sep 2010 12:20:29 GMT"; "Keep-Alive" = "timeout=3, max=148"; Server = Apache; "Transfer-Encoding" = Identity; Vary = "Accept-Encoding"; "X-Powered-By" = "PHP/5.2.13"; "X-Uncompressed-Content-Length" = 282888;
请注意,没有给出Content-Length。
我的问题:
这个应用程序可以用于昂贵的数据计划,因此我希望向用户报告实际使用情况,而不是使用30-70%的夸大使用量(几百KB的额外听起来可能不是很多 – 但是这些计划可能花费1美元和每MB 10美元!)。
提前致谢。
除了Martin Fjordvalds回答:
仅当压缩文件大小大于DeflateBufferSize时,Apache才会使用分块编码。 因此,增加此缓冲区大小将防止服务器对较大文件使用分块编码,从而导致即使对于压缩数据也会发送内容长度。
更多信息可以在这里find: http : //httpd.apache.org/docs/2.2/mod/mod_deflate.html#deflatebuffersize
听起来像Apache正在做分块编码,这意味着它可以发送数据,因为它正在被压缩,而不是等待完整的响应被压缩。 这是相当标准的做法,但是我对Apache不太熟悉,不知道它是否可以被禁用。
好的,我设法解决了这个问题。 正如Martin F正确地指出的那样,Apache正在分块回应,所以内容大小不得而知。 对于很多人来说,这是可取的(页面加载速度更快)。 这是以无法报告下载进度为代价的。
对于那些真正想要报告下载进度的人,如果您使用Apache或PHP的自动gzip支持,那么您可以做的事情很less。 解决办法是手动完成。 这比听起来容易:
如果你发送整个文件,那么这是一个很好的例子,在PHP中强制一个块(与内容长度): http : //www.php.net/manual/en/function.ob-start.php #94741
如果您发送生成的数据,那么使用gzencode来编码您的数据,就像上面的示例一样。 一个先决条件是所有的输出数据都存储在一个variables中(如果需要缓冲,可以使用ob_start来获得帮助,然后获取缓冲区的内容)。
// $replyBody is the entire contents of your reply header("Content-Type: application/json"); // or whatever yours is // checks if gzip is supported by client $pack = true; if(empty($_SERVER["HTTP_ACCEPT_ENCODING"]) || strpos($_SERVER["HTTP_ACCEPT_ENCODING"], 'gzip') === false) { $pack = false; } // if supported, gzips data if($pack) { header("Content-Encoding: gzip"); $replyBody = gzencode($replyBody, 9, FORCE_GZIP); } // compressed or not, sets the Content-Length header("Content-Length: " . mb_strlen($replyBody, 'latin1')); // outputs reply & exits echo $replyBody; exit;
瞧!
自己做的另一个好处是可以设置压缩级别。 这对于我的移动应用程序是非常好的,因为我可以将其设置为最高的压缩级别(所以我的用户为数据支付更less的费用!) – 而服务器可能只使用中等压缩级别来实现更好的CPU /尺寸折衷。 压缩级别是我相信只有编辑httpd.conf(在共享主机上,我不能)才能改变。
所以我保留了我的DEFLATE .htaccess指令,除了我现在用上面的方法编码的application / json回复。
再次感谢Martin F,你给我的火花我需要解决这个:)