|
|
 |
ob_gzhandler (PHP 4 >= 4.0.4, PHP 5) ob_gzhandler --
ob_start callback function to gzip output buffer
Descriptionstring ob_gzhandler ( string buffer, int mode ) Note:
ob_gzhandler() requires the zlib
extension.
ob_gzhandler() is intended to be used as a
callback function for ob_start() to help
facilitate sending gz-encoded data to web browsers that support
compressed web pages. Before ob_gzhandler()
actually sends compressed data, it determines what type of
content encoding the browser will accept ("gzip", "deflate" or
none at all) and will return its output accordingly. All
browsers are supported since it's up to the browser to send the
correct header saying that it accepts compressed web pages.
Note:
mode was added in PHP 4.0.5.
Example 1. ob_gzhandler() example |
<?php
ob_start("ob_gzhandler");
?>
<html>
<body>
<p>This should be a compressed page.</p>
</html>
<body>
|
|
See also
ob_start() and
ob_end_flush().
User Contributed Notes
ob_gzhandler
m at rtij dot nl
16-Apr-2005 07:29
All versions of MSIE have a bug where they don't cache gzipd contents. If your application depends on caching, this is something to keep in mind. In the end, I did:
<?php
if (!isset($use_page_cache))
$use_page_cache = 1;
if (!isset($use_compression))
$use_compression = 1;
$browser="other";
if (isset($_SERVER['HTTP_USER_AGENT'])) {
$agent = $_SERVER['HTTP_USER_AGENT'];
if (eregi("opera",$agent)){
$browser="opera";
}elseif(eregi("msie",$agent)){
$browser="msie";
}
}
if ($use_compression && !( $use_page_cache && $browser == "msie")) {
ob_start('ob_gzhandler');
}
session_cache_limiter("must-revalidate");
session_start();
if ($use_page_cache) {
$hash = md5($content);
$headers = getallheaders();
if (isset($headers['If-None-Match']) && ereg($hash, $headers['If-None-Match']))
{
header('HTTP/1.1 304 Not Modified');
exit;
}
header("ETag: \"$hash\"");
}
print $content;
?>
grange (at) club-internet (dot) fr
07-Mar-2005 09:17
It may seem obvious but if you use ob_start("ob_gzhandler"), make sure no content is unintentionally echo'ed before : this could be blank lines before '<?php' or after '?>' tags in included files or even errors.
Otherwise, only a part of the content (the content sent after ob_start()) will be compressed, which will confuse the client.
Setting compression using zlib.output_compression either in php.ini or in Apache configuration file (with directive php_flag) is safer in this regard.
wallacebw at some-domain dot com
21-Feb-2005 11:50
IE 6+ appears to validate the CRC and disgard invalid gzip content FYI...
Brian
andy dot rem dot ove dot this at occ dot be
01-Apr-2004 04:21
mazsolt at yahoo dot com
18-Mar-2004 09:20
if you want to send an output to the browser (which accepts gzip), and you haven't set the buffering callback ob_start("ob_gzhandler"), you may use the gzencode() function.
header("Content-Encoding: gzip");
echo gzencode("some output", 9, FORCE_GZIP);
daijoubuNOSP at Mvideotron dot ca
27-Oct-2003 04:05
So much code...here's a lighter/faster one:
<?php
if ( $do_gzip_compress )
{
$gzip_size = ob_get_length();
$gzip_contents = ob_get_clean(); echo "\x1f\x8b\x08\x00\x00\x00\x00\x00",
substr(gzcompress($gzip_contents, 9), 0, - 4), pack('V', crc32($gzip_contents)), pack('V', $gzip_size); }
exit;
?>
I wouldn't recommande using level 9, waste of CPU, something between 1 and 6 would be more resonable
I have tested without the substr/crc/size and it worked flawlessly in IE5/5.5/6, Opera7.11/7.21, IE5.5 MAC
brewthatistrue at plzYnoAspamHorOevilO dot com
21-Sep-2003 04:04
i had a LOT of trouble trying to get gzipping working correctly
i kept getting a blank page on the first load, although subsequent pages loaded fine.
i tried stuff with ob_flush and ob_end_clean and all kinds of stuff i didn't understand. i'm totally confused about different versions of php and different methods of gzipping.
in the end, i got it working (maybe i'll understand it later).
i ended up using phpBB's code (stripped of non-gz stuff, and ever-so-slightly modified)
http://phpbb.com/
index.php:
------------
<?php
require_once('top.php');
echo "<html>\n<head>\n<title>Gzip Test</title>\n<body>\n<h1>testing</h1>\n</body>\n</html>";
require_once('bottom.php');
?>
gz_header.php - taken form phpBB's page_header.php
--------------
<?php
$phpver = phpversion();
$useragent = (isset($_SERVER["HTTP_USER_AGENT"]) ) ? $_SERVER["HTTP_USER_AGENT"] : $HTTP_USER_AGENT;
if ( $phpver >= '4.0.4pl1' && ( strstr($useragent,'compatible') || strstr($useragent,'Gecko') ) )
{
if ( extension_loaded('zlib') )
{
ob_start('ob_gzhandler');
}
}
else if ( $phpver > '4.0' )
{
if ( strstr($HTTP_SERVER_VARS['HTTP_ACCEPT_ENCODING'], 'gzip') )
{
if ( extension_loaded('zlib') )
{
$do_gzip_compress = TRUE;
ob_start();
ob_implicit_flush(0);
header('Content-Encoding: gzip');
}
}
}
?>
gz_footer.php - taken form phpBB's page_tail.php
------------
<?php
if ( $do_gzip_compress )
{
$gzip_contents = ob_get_contents();
ob_end_clean();
$gzip_size = strlen($gzip_contents);
$gzip_crc = crc32($gzip_contents);
$gzip_contents = gzcompress($gzip_contents, 9);
$gzip_contents = substr($gzip_contents, 0, strlen($gzip_contents) - 4);
echo "\x1f\x8b\x08\x00\x00\x00\x00\x00";
echo $gzip_contents;
echo pack('V', $gzip_crc);
echo pack('V', $gzip_size);
}
exit;
?>
i must admit to not seeing this working in opera 7.11. perhaps i will figure that one out.
if there is anything i should change email me and i can edit my post
jazfresh at SPAM-JAVELIN dot hotmail dot com
18-Sep-2003 09:54
In the set_error_handler notes, there is a technique described for capturing all errors (even parse errors) before they are displayed the user, using a special error handler and output handler. If this output handler detects a fatal error in the output buffer, it's captured and dealt with before it can be displayed to the user. If no error was detected, then output buffer is displayed verbatim (i.e. without being compressed).
If you are using this method, you can still take advantage of ob_gzhandler's compression. However, you MUST specify a mode argument (I'm using 4.2.2 on RedHat9). The mode value affects which headers are automatically added (Content-Encoding, etc). A value of '5' worked for me. '0' or discarding the argument produces a blank screen under Mozilla.
<?php
function my_output_handler(&$buffer) {
if(ereg("(error</b>:)(.+) in <b>(.+)</b> on line <b>(.+)</b>", $buffer, $regs)) {
my_error_handler(E_ERROR, $regs[2], $regs[3], $regs[4]);
return 'An internal error occurred.';
} else {
return ob_gzhandler($buffer, 5);
}
}
?>
daijoubu at videotron dot ca
06-Sep-2003 06:35
About the previous note from Davey:
ob_start(array('ob_gzhandler',9));
Does not work. The output size isn’t affected at all, stays the same.
ob_gzhandler compression level use zlib.output_compression_level, which is -1 per default, level 6.
To change the compression level on the fly, simply use ini_set:
<?php
ini_set('zlib.output_compression_level', 1);
ob_start('ob_gzhandler');
echo 'This is compressed at level 1';
?>
nospam at 1111-internet dot com
15-Apr-2003 03:47
Following up on my previous post - it appears that while:
<?php
ini_set("zlib.output_compression", "Off"); ?>
did not work in php 4.2.3, it did begin to work as of php 4.3.0 as an override to the php.ini "zlib.output_compression=on" setting. I did not see this in the change log.
In light of this, I'd say using zlib.output_compression is definitely the way to go over ob_gzhandler() in most cases.
09-Apr-2003 12:47
When using ob_start("ob_gzhandler"), be aware that the output buffer has to be flushed in order to invoke the ob_gzhandler callback function.
This may not always happen. For example, if you use ob_get_contents() to copy the output buffer to a string for further manipulation and then silently discard the buffer with ob_end_clean(), the output buffer is never "flushed" and as a result, the ob_gzhandler callback function is never invoked. And your pages won't be compressed.
This will be the case, for example, if you use the PHP Fusebox architecture/framework.
davey at its-explosive dot net
03-Apr-2003 08:41
To pass the second argument to ob_gzhandler() which specifies what level of compression should be used (which I assume is 1-9 as with the gzip binary, with 9 using the most processor and time to do, 4 is the standard IIRC) you must call ob_start() like so:
ob_start(array('ob_gzhandler',9));
- Davey
nospam at 1111-internet dot com
08-Mar-2003 05:23
Differences between zlib.output_compression and ob_gzhandler:
zlib.output_compression runs in parallel with script execution - it begins compressing as soon as it receives any output from your script, and sends data to the client each time its buffer (4K by default) gets full. ob_gzhandler (actually 'ob_start("ob_gzhandler");') will not start compressing until the script flushes (or, usually, exits), and will in turn send the entire compressed document at once - which makes it more susceptible to causing a perception of latency.
Advantage: zlib.output_compression
On the other hand, ob_gzhandler gives you script-level control allowing you to use it selectively or to unset it after setting it in certain cases. Despite some documentation to the contrary, zlib.output_compression does not appear to be able to be set or unset on a script level; you must instead set it globally (in php.ini) or in your webserver configs or .htaccess files, possibly using FilesMatch-type mechanisms to control which scripts it will or won't apply to - which could get unwieldy for large projects - particularly those which employ PHP to produce images and other non-text output in addition to normal text output.
Advantage: ob_gzhandler
Net advantage: depends on your particular needs. I'm trying zlib.output_compression for now, but I miss the flexibility that ob_gzhandler would provide.
p.s. here's an Apache 1.3.* httpd.conf/.htaccess file snippet that demonstrates the syntax for conditionally setting zlib.output_compression:
<FilesMatch "\.(php|html?)$">
# turn it on with the buffer set to 2K using php_value
php_value zlib.output_compression 2048
# or just turn it on using php_flag
# php_flag zlib.output_compression On
</FilesMatch>
aki at robotnik dot net
04-Mar-2003 01:13
if you get errors like:
"output handler 'ob_gzhandler' cannot be used twice"
if you are using
"ob_start("ob_gzhandler");"
check for your php.ini file, it should look like this:
output_buffering = Off ; delete the 4096k value
output_handler =
zlib.output_compression = Off
dsugar100 at dolphinsoft dot com
06-Nov-2002 05:33
I have noticed that if you have the php setting for zlib.output_compression set to 'On' AND you attempt to use hte ob_gzhandler handler to ob_start () the output you get in the browser WILL be garbled in PHP 4.2.3. I'm guessing that the output buffering is compressing the output to be sent, and then zlib is doing it a second time, but the browser is only uncompressing it once.
But using either one will give you the same results (compressed output from the script)
nid at home dot se
30-Sep-2002 06:10
If you are trying to use the ob_gzhandler in a MSHTA (Microsoft HTML Application) you will find that your pages does not show up. the MSHTA-browser probably says it can handle gzip, but it just won't work (IE:6, PHP:4.1.2)
psychones at ifrance dot com
08-Aug-2002 07:18
Problem revelate by xn@bnw.com
cause real problem when you have a global call
to ob_gzhandler , for example in an include configuration
file , and you want send a non gzip content , for any reason ...
To resolve it ,
put this after your global call to ob_gzhandler
include("conf_that_call_ob_gzhandler.php");
-->ob_end_clean();
-->header("Content-Encoding: none");
If you try to overload the header before the the ob_gzhandler call
or during the buffering output , it will not work .
( probably erase at the call of ob_gzhandler and not allow during
buffering ).
Hope this help
isoma at altavista dot net
24-Jun-2002 09:44
RFC 2616 suggests that a more correct way to compress documents on the fly is to use gzip transfer encoding rather than gzip content encoding. However, it's perhaps not advisable to use this since client support for it is extremely limited.
The difference is most evident when you come to save a file from your browser. If it's gzip content encoded then the browser should (and may well) save it gzipped. If it's gzip transfer encoded then the browser should uncompress it first.
Sven dot Dickert at planb dot de
29-May-2002 06:54
Following Browsers send
Accept-Encoding: gzip
but have Problems with
Content-Encoding: gzip
* netscape < 5 have problems with CSS/Javascript parts sendet in gzip
* opera 5.x,6 store downloads compressed
* lynx 2.8.4 store downloads compressed but tells this with attaching ".gz" to the filename
You should know about:
* Internet Explorer 5.x,6 should turned to HTTP 1.1 to get "Accept-Encoding: gzip"
* In Mozilla 1.0 RC2 you can write the "Accept-Encoding:" in Preferences/Advanced/HTTP Networking
xn at bnw dot com
12-Apr-2002 10:40
if you call ob_end_clean() after ob_start("ob_gzhandler"), the "Content-Encoding: gzip" header will still get sent (assuming the browser supports the encoding). if you don't call ob_start() again with the ob_gzhandler callback function, the output will not be compressed, but the header will say it is. this causes mozilla (as of build 2002032808) to display a blank page.
junior at jaj dot com
04-Mar-2002 12:12
To get this to work properly, you have to compile PHP with "--with-zlib". If you don't, you won't get any errors, it just won't actually compress anything. This is a phenomenal thing. For just a small bit of processor time, you can DRASTICALLY reduce the bandwidth requirement of your scripts. There are very few circumstances in which this should not be used.
| |