7

I'm working on a PHP script which generates large (multi-MB) output on the fly without knowing the length in advance. I am writing directly to php://output via fwrite() and have tried both standard output and using Transfer-Encoding: chunked (encoding the chunks as required) but no matter what I try the browser waits until all the data is written before displaying a download dialog. I have tried flush()ing too after the headers and after each chunk but this also makes no difference.

I'm guessing that Apache is caching the output as the browser would normally display after receiving a few kB from the server.

Does anyone have any ideas on how to stop this caching and flush the data to the browser as it is generated?

Thanks, J

5
  • 1
    Rather than guess that apache isn't flushing until the entire contents are generated, I suggest using wireshark or similar tools to see what data is being sent to the browser. Insert some sleep(1) calls if you need to slow things down. (I doubt Apache maintains several megabytes on a single socket before flushing its buffers.) Commented Aug 13, 2010 at 9:57
  • 3
    My guess would be, that you have GZIP compression enabled in either php.ini and/or apache config. In that case apache always caches. Haven't found a way to avoid this (other than disabling compression), so lets see what other people know about this. Might be a question for serverfault.com, though... Commented Aug 13, 2010 at 9:58
  • @sarnold - When I say I'm guessing it is an educated guess as I've been tracking the request through Fiddler and do not see any response until the download dialog appears so I'm quite confident that it is caching at the server side. @BlaM - You are absolutely correct in saying that GZIP is enabled, I didn't think of that as a possible cause as it's a streaming compression algo but that may be the problem. I will try disabling for this particular script and see what happens. Thanks. Commented Aug 13, 2010 at 10:10
  • @user290796, aha, that's not really "guessing" then! :) If @BlaM is right, perhaps you could write your own Apache output filter to send periodic FLUSH buckets, to keep the benefits of gzip. (Seems really useful with huge files to keep it.) Commented Aug 13, 2010 at 10:44
  • True, although I wasn't 100% sure that Fiddler wasn't waiting for the complete output before displaying so it was guessing slightly ;). The file being output is actually a ZIP file anyway so it's already compressed so there may not be a huge benefit in keeping GZIP but an output filter may be an option. I'm not near the server right now to try disabling GZIP but I will give it a try later today. Commented Aug 13, 2010 at 10:57

1 Answer 1

1

First of all, like BlaM mentioned in his comment, if in the PHP configuration OutputBuffering is enabled, it wont work, so it would be useful to know your phpinfo().

Next thing, try if it works with a big file that is stored on yor webserver, output it usinf readfile. And, together with this, check if you send the correct headers. Hints on how to readfile() and send the correct headers a provided here: StackOverflow: How to force a file download in PHP

And while you are at it, call ob_end_flush() or ob_end_clean() at the top of your script.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.