PHP 手动 GZip 编码

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5699020/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 22:15:59  来源:igfitidea点击:

PHP Manual GZip Encoding

phpencodinggzipcompression

提问by M.Alnashmi

I was testing my website with Page Speed and the result was around 70/100. Enable Compression was the first and most important factor in slowing it down.

我正在用 Page Speed 测试我的网站,结果大约是 70/100。启用压缩是降低速度的第一个也是最重要的因素。

I know that I can do that by modifying the php.ini to automatically do that but I was more interested in the manual method (gzencode).

我知道我可以通过修改 php.ini 来自动执行此操作,但我对手动方法 ( gzencode)更感兴趣。

The problem is either all browsers fail in opening the website (Firefox: "The page you are trying to view cannot be shown because it uses an invalid or unsupported form of compression.", Chrome: "303, ERR Content Encoding", etc.) or they display the encoded string.

问题是所有浏览器都无法打开网站(Firefox:“您尝试查看的页面无法显示,因为它使用了无效或不受支持的压缩形式。”,Chrome:“303,ERR 内容编码”等。 ) 或者它们显示编码的字符串。

Live Headers shows that the browser accepts the encoding, and the response has the content type set, but it still fails.

Live Headers 显示浏览器接受编码,并且响应设置了内容类型,但仍然失败。

GET / HTTP/1.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip,deflate

HTTP/1.1 200 OK
Content-Encoding: gzip
Content-Length: 5827
Vary: Accept-Encoding


private function _compress($data) {
    //return trim(preg_replace(array('/\>[^\S ]+/s','/[^\S ]+\</s','/(\s)+/s'), array('>','<','\1'), $data));
    $supportsGzip = strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false;

    ob_start();
    if ($supportsGzip) {
        echo gzencode(trim(preg_replace('/\s+/', ' ', $data)), 9);
    } else {
        echo $data;
    }

    $content = ob_get_contents();
    header("content-type: text/html; charset: UTF-8");
    header("cache-control: must-revalidate");
    $offset = 60 * 60;
    $expire = "expires: " . gmdate("D, d M Y H:i:s", time() + $offset) . " GMT";
    header($expire);
    header('Content-Length: ' . strlen($content));
    header('Vary: Accept-Encoding');
    ob_end_clean();
    echo $content;
}

If I change the Content-Encoding to zlib, I get the encoded string:

如果将 Content-Encoding 更改为 zlib,则会得到编码字符串:

????????Z?s???W^‘¥2o‘¨/–-?–ú?‰_?μ??ú_v I°I?!A?j–?on??b·?%íú?2n???‘t?=¤L)',?Iw>?Eax?á?÷°ùT?O??????tl??μ·? $k??? ?^?<ü??\?? ?o—\??6???”^?0z?^?Wê ?m4?j?°…X?'??|?nS·]#ì?F-|8LRPL2ìIè?52-\é\?m?=Fà?J5"ù—RóY?3CyéZ([ù?b%1′Yy??á?cx}±iD′??KV#4”á§x>?°à?íò ?p????1?ì?‘@?m

I don't really care anymore about getting the compression as much as I want to know why its not working.

我真的不再关心压缩了,因为我想知道它为什么不起作用。

Cheers,

干杯,

回答by Craig Sefton

Well, I think it's because you're trying to compress an empty string.

好吧,我认为这是因为您试图压缩一个空字符串。

I took your script as you gave it, and ran it in FF and IE.

我拿了你给的脚本,并在 FF 和 IE 中运行它。

Both failed, and FF said that there was an issue (like you described).

都失败了,FF 说有问题(就像你描述的那样)。

However, I then noticed $data is an empty string.

但是,我随后注意到 $data 是一个空字符串。

When I set $data = "Some test data.";at the top of the file it worked immediately (browser displayed "Some test data."), and checking in Firebug, I can see the correct headers.

当我$data = "Some test data.";在文件顶部设置它时它立即工作(浏览器显示“一些测试数据。”),并检查 Firebug,我可以看到正确的标题。

Content-Encoding    gzip
Content-Length  68
Vary    Accept-Encoding
Content-Type    text/html

Edit:Also, just to point out, your if ($supportsGzip) {is a bit odd, because your else condition should actually echo out $data, not $content.

编辑:另外,要指出的是,您的 if ($supportsGzip) {情况有点奇怪,因为您的 else 条件实际上应该回显出来$data,而不是$content.

Edit:Okay, based on your revised function above, there are two key problems.

编辑:好的,根据你上面修改的函数,有两个关键问题。

The primary problem has to do with the fact that you're wiping out your headers by calling ob_end_clean(). A comment on the PHP Docsstates that "ob_end_clean() does discard headers".

主要问题与您通过调用ob_end_clean(). PHP Docs上的评论指出“ob_end_clean() 确实会丢弃标头”。

This means any headers you set before calling ob_end_clean()will get wiped. Also, your revised function doesn't send a gzip encoding header, either.

这意味着您在调用之前设置的任何标头都ob_end_clean()将被擦除。此外,您修改后的函数也不会发送 gzip 编码标头。

I must say that there is probably no need to even use ob_start and related functions here, either. Try the following:

我必须说,这里可能甚至不需要使用 ob_start 和相关函数。请尝试以下操作:

function _compress( $data ) {

    $supportsGzip = strpos( $_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip' ) !== false;


    if ( $supportsGzip ) {
        $content = gzencode( trim( preg_replace( '/\s+/', ' ', $data ) ), 9);
        header('Content-Encoding: gzip');
    } else {
        $content = $data;
    }

    $offset = 60 * 60;
    $expire = "expires: " . gmdate("D, d M Y H:i:s", time() + $offset) . " GMT";

    header("content-type: text/html; charset: UTF-8");
    header("cache-control: must-revalidate");
    header( $expire );
    header( 'Content-Length: ' . strlen( $content ) );
    header('Vary: Accept-Encoding');

    echo $content;

}

_compress( "Some test data" );

This works in IE and FF, but I didn't have time to test other browsers.

这适用于 IE 和 FF,但我没有时间测试其他浏览器。

If you really must use ob_start and related functions, make sure you set your headers after you call ob_end_clean().

如果您确实必须使用 ob_start 和相关函数,请确保在调用ob_end_clean().

回答by daschl

I'd suggest to use http://php.net/manual/de/function.ob-gzhandler.php, this works out of the box for me:

我建议使用http://php.net/manual/de/function.ob-gzhandler.php,这对我来说是开箱即用的:

In my index.php I just place this before some output:

在我的 index.php 中,我只是将它放在一些输出之前:

    /**
     * Enable GZIP-Compression for Browser that support it.
     */
    ob_start("ob_gzhandler");

And it encodes it!

它编码它!

回答by Jens Roland

A few things:

一些东西:

  1. You probably want to add another header: header('Content-Encoding: gzip');

  2. You are using ob_end_clean, which deletes all echoed/printed content without sending it to the browser. Depending on what you're trying to do, you may want to use ob_flush instead.

  3. To make sure your output is buffered and handled (and compressed if you use PHP's output buffering compression), make sure all echo/print statements are placed BETWEEN the ob_start and ob_flush sttements.

  1. 您可能想添加另一个标题: header('Content-Encoding: gzip');

  2. 您正在使用 ob_end_clean,它会删除所有回显/打印的内容,而不将其发送到浏览器。根据您要执行的操作,您可能希望改用 ob_flush。

  3. 为了确保你的输出被缓冲和处理(如果你使用 PHP 的输出缓冲压缩,则被压缩),确保所有的 echo/print 语句都放在 ob_start 和 ob_flush 语句之间。

--and then try it again :)

--然后再试一次:)