PHP flush stopped flushing in IIS7.5

泄露秘密 提交于 2019-11-27 22:29:28
Justin

You must set the ResponseBufferLimit value of the desired handler to a number low enough to actually flush. I recommend using 0 since it prevents IIS from doing anything but passing along what you send it from your PHP script. You can use the following command line to set the ResponseBufferLimit to 0 for the php handler (just change “NAME” to the name of the handler you want to update e.g. PHP53_via_FastCGI):

appcmd.exe set config /section:handlers "/[name='NAME'].ResponseBufferLimit:0"

Alternatively, you can edit the applicationHost.config directly and add a ResponseBufferLimit attribute the XML element.

There is another way to set the Response Limit using the IIS Manager:

  1. On the server main page, under "Management", select "Configuration Editor";
  2. under "Section", enter 'system.webServer/handlers';
  3. next to "(Collection)" click "..." OR mark the element "(Collection)" and, under "Actions" und '(Collection)' Element, click "Edit Items";
  4. scroll down until you find your PHP version under "Name";
  5. at the bottom, the Properties are shown an can be edited manually, including responseBufferLimit, which should be set to 0 for flush() to work.

The big Pro is that you can edit the properties for everything, not only PHP plus you can work with different versions (or even installations of the same version) of PHP.

HTH

knatsch

Enter the following command as Administrator in Powershell:

C:\Windows\System32\inetsrv> .\appcmd.exe set config /section:handlers "/[name='PHP_via_FastCGI'].ResponseBufferLimit:0"

Expected Output:

Applied configuration changes to section "system.webServer/handlers" for "MACHINE/WEBROOT/APPHOST" at configuration comm it path "MACHINE/WEBROOT/APPHOST"

For more background, have a look at: http://www.coastrd.com/cgioniis7

Basically, we need to tell FastCGI to turn of its ResponseBufferLimit. This cannot be done through the IIS Management Console (checked only 7.5)

What I do is that I use the following function:

function flush_buffers(){
    ob_end_flush();
    ob_flush();
    flush();
    ob_start();
}

So in your code:

ob_start();
flush_buffers();

echo "starting...<br/>\n";
for($i = 0; $i < 5; $i++) {
    print "$i<br/>\n";
    flush_buffers();
    sleep(2);
}

It should work flawlessly :-)


Here is some working code (with correct Content-Type set):

<?php
header("Content-Type: text/html; charset=utf-8");
function flush_buffers(){
    ob_end_flush();
    ob_flush();
    flush();
    ob_start();
}

ob_start();
flush_buffers();
echo "starting...<br/>\n";
for($i = 0; $i < 60; $i++) {
    flush_buffers();
    print   "$i<br/>\n";
    flush_buffers();
    sleep(2);
}

flush_buffers();

print "DONE!<br/>\n";
?>

I'm a little late to the party, but thought I'd add how to do this with web.config.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
        <!--- other stuff here --->
        <handlers>
            <remove name="ISAPI-dll" />
            <add name="ISAPI-dll" path="*.dll" verb="*" type="" modules="IsapiModule" scriptProcessor="" resourceType="File" requireAccess="Execute" allowPathInfo="true" preCondition="" responseBufferLimit="0" />
        </handlers>
    </system.webServer>
</configuration>

It's up to the webserver whether it decides to naggle the content or send it via chunked encoding. So although PHP can ask the server to push data out to the client, it can't force the server to use chunked encoding.

This article suggests you explicitly need to set the transfer encoding for IIS (see the bit about ISAPI) for sending data to the server - you might try the same in your script.

IME, most scenarios where this is an issue can be better dealt with by....

register_shutdown_function('do_slow_stuff');
....generate html content....
exit; // closes stdin/stdout, but shutdown fn will still be called 

function do_slow_stuff()
{
  ....
} 

Here's another way of doing this with web.config (@Jules's method didn't work for me with IIS 8.0). Of course, you would want to replace the PHP versions and paths with the ones actually on your machine.

This allows the usage of server-sent events!

<configuration>
    <system.webServer>
        <handlers>
            <remove name="PHP53_via_FastCGI" />
            <remove name="PHP54_via_FastCGI" />
            <remove name="PHP55_via_FastCGI" />
            <add name="PHP53_via_FastCGI" path="*.php" verb="GET,HEAD,POST" type="" modules="FastCgiModule" scriptProcessor="C:\Program Files (x86)\PHP\v5.3\php-cgi.exe" resourceType="Either" requireAccess="Script" allowPathInfo="true" preCondition="" responseBufferLimit="0" />
            <add name="PHP54_via_FastCGI" path="*.php" verb="GET,HEAD,POST" type="" modules="FastCgiModule" scriptProcessor="C:\Program Files (x86)\PHP\v5.4\php-cgi.exe" resourceType="Either" requireAccess="Script" allowPathInfo="true" preCondition="" responseBufferLimit="0" />
            <add name="PHP55_via_FastCGI" path="*.php" verb="GET,HEAD,POST" type="" modules="FastCgiModule" scriptProcessor="C:\Program Files (x86)\PHP\v5.5\php-cgi.exe" resourceType="Either" requireAccess="Script" allowPathInfo="true" preCondition="" responseBufferLimit="0" />
        </handlers>
    </system.webServer>
 </configuration>
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!