I'm using echo
to output various files to browser, including some 10MB+ .swf files. A negative side effect I'm experiencing is that it seems to mess up with some flash preloaders in the content, causing the image to flicker instead of showing a steady progress bar, for example. I wonder if there is any kind of buffering going on or anything else I can do to fix it.
For some background info, the reason I have to feed the content indirectly is that it is designed to only be served to authorized users, so the script first checks that the user has appropriate permissions, then pairs up readfile()
with echo
. Maybe there is a nicer way of doing it altogether, I'm open to ideas.
Edit:
readfile()
and echo
are a simplified way of explaining it, of course. It runs something like:
<?php
check_valid_user();
ob_start();
// set appropriate headers for content-type etc
set_headers($file);
readfile($file);
$contents = ob_get_contents();
ob_end_clean();
if (some_conditions()) {
// does some extra work on html files (adds analytics tracker)
}
echo $contents;
exit;
?>
You could probly use fopen / fread etc in tandem w/ echo & flush. You probly need a call to header to set the content type beforehand if you aren't already. Also if you're using output buffering you'll need to call ob_flush.
In this way you can read smaller pieces of data and echo them immediately rather than needing to buffer the entire file prior to output.
You might want to try setting the Content-Length header.
Something like
header('Content-Length: ' . filesize($file));
I think that buffering is superfluous in this case. You might do:
<?php
check_valid_user();
// set appropriate headers for content-type etc
set_headers($file);
if (some_conditions())
{
$contents = file_get_contents($file);
// does some extra work on html files (adds analytics tracker)
// Send contents. HTML is often quite compressible, so it is worthwhile
// to turn on compression (see also ob_start('ob_gzhandler'))
ini_set('zlib.output_compression', 1);
die($contents);
}
// Here we're working with SWF files.
// It may be worthwhile to turn off compression (SWF are already compressed,
// and so are PDFs, JPEGs and so on.
ini_set('zlib.output_compression', 0);
// Some client buffering schemes need Content-Length (never understood why)
Header('Content-Length: ' . filesize($file));
// Readfile short-circuits input and output, so doesn't use much memory.
readfile($file);
// otherwise:
/*
// Turn off buffering, not really needed here
while(ob_get_level())
ob_end_clean();
// We do the chunking, so flush always
ob_implicit_flush(1);
$fp = fopen($file, 'r');
while(!feof($fp))
print fread($fp, 4096); // Experiment with this buffer's size...
fclose($fp);
?>