Continue Processing After Closing Connection

Continue processing after closing connection

I finally found a solution (thanks to Google, I just had to keep trying different combinations of search terms). Thanks to the comment from arr1 on this page (it's about two thirds of the way down the page).

<?php
ob_end_clean();
header("Connection: close");
ignore_user_abort(true);
ob_start();
echo 'Text the user will see';
$size = ob_get_length();
header("Content-Length: $size");
ob_end_flush(); // All output buffers must be flushed here
flush(); // Force output to client
// Do processing here
sleep(30);
echo('Text user will never see');

I have yet to actually test this but, in short, you send two headers: one that tells the browser exactly how much data to expect then one to tell the browser to close the connection (which it will only do after receiving the expected amount of content). I haven't tested this yet.

Continue php script after connection close

After some research i got it work, Sometime it may be useful to some others.

function closeOutput($stringToOutput){   
set_time_limit(0);
ignore_user_abort(true);
header("Connection: close\r\n");
header("Content-Encoding: none\r\n");
ob_start();
echo $stringToOutput;
$size = ob_get_length();
header("Content-Length: $size",TRUE);
ob_end_flush();
ob_flush();
flush();
}

You can use it like

$outputContent = 'Contentent Goes Here...';

closeOutput( $outputContent );

sleep(5);

//do some background works ...

exit();

Close a Connection, but continue to do Processing

This works on Apache (and apparently not on IIS with FastCGI)

<?php
ignore_user_abort(true); // make sure PHP doesn't stop when the connection closes

// fire and forget - do lots of stuff so the connection actually closes
header("Content-Length: 0");
header("Connection: Close");
flush();
session_write_close(); // if you have a session

do_processing();
// don't forget to `set_time_limit` if your process takes a while

PHP close HTTP connection then continue processing?

Headers are sent whenever the first byte is output to the browser.

You could also try to use ob_end_flush();

Compress a manually closed connection AND continue processing

I managed to reduce the code in thanks to a comment by Rush on the ob_get_length documentation page. All three flush commands are required, commenting out any of them results in the page not loading until after sleep(4). I tested this to ensure that the connection closed in the browser, was compressed and then switched over to my file manager to see the file created a few seconds later.

<?php
ob_start();
ob_start('ob_gzhandler');

// Send your response.
echo '<style>* {background-color: #000; color: #fff;}</style>';
echo '<p>Testing response: '.time().'.</p>';

// The ob_gzhandler one
ob_end_flush();

header('Content-Length: '.ob_get_length());

// The main one
ob_end_flush();
ob_flush();
flush();

// Close current session (if it exists).
if (session_id()) {session_write_close();}

sleep(4);
file_put_contents('test.txt', 'testing: '.time().'; size: '.$size);
?>

Will a script continue to run even after closing a page?

See here:
http://php.net/manual/en/function.ignore-user-abort.php

int ignore_user_abort ([ bool $value ] )

Sets whether a client disconnect should cause a script to be aborted.

When running PHP as a command line script, and the script's tty goes away without the script being terminated then the script will die the next time it tries to write anything, unless value is set to TRUE

There also is a PHP configuration option of the same name:
http://php.net/manual/en/misc.configuration.php

By default, if you do nothing, according to the PHP manual the default is to abort the script.
http://php.net/manual/en/features.connection-handling.php

NECESSARY UPDATE

It seems I (unknowingly) tricked my way to "reputation points", because I did NOT supply the (correct) answer, but here it is now thanks to testing and continued nudging from "mellamokb":

Quote:
"Ok, I took a look at the PHP source code and, if I didn't miss anything, I now have the answer. The "ignore_user_abort" flag is only checked when PHP receive an error trying to output something to the user. So, in my understanding, there is no way to interrupt code which doesn't produce any output."

Okay, I wasn't totally off, but it is important to know that it all depends on whether or not your script produced any output!

If you read THIS, also DO check out the comments below.

How do I close a connection early?

The following PHP manual page (incl. user-notes) suggests multiple instructions on how to close the TCP connection to the browser without ending the PHP script:

  • Connection handling Docs

Supposedly it requires a bit more than sending a close header.


OP then confirms: yup, this did the trick: pointing to user-note #71172 (Nov 2006) copied here:

Closing the users browser connection whilst keeping your php script running has been an issue since [PHP] 4.1, when the behaviour of register_shutdown_function() was modified so that it would not automatically close the users connection.

sts at mail dot xubion dot hu Posted the original solution:

<?php
header("Connection: close");
ob_start();
phpinfo();
$size = ob_get_length();
header("Content-Length: $size");
ob_end_flush();
flush();
sleep(13);
error_log("do something in the background");
?>

Which works fine until you substitute phpinfo() for echo('text I want user to see'); in which case the headers are never sent!

The solution is to explicitly turn off output buffering and clear the buffer prior to sending your header information. Example:

<?php
ob_end_clean();
header("Connection: close");
ignore_user_abort(true); // just to be safe
ob_start();
echo('Text the user will see');
$size = ob_get_length();
header("Content-Length: $size");
ob_end_flush(); // Strange behaviour, will not work
flush(); // Unless both are called !
// Do processing here
sleep(30);
echo('Text user will never see');
?>

Just spent 3 hours trying to figure this one out, hope it helps someone :)

Tested in:

  • IE 7.5730.11
  • Mozilla Firefox 1.81

Later on in July 2010 in a related answer Arctic Fire then linked two further user-notes that were-follow-ups to the one above:

  • Connection Handling user-note #89177 (Feb 2009)
  • Connection Handling user-note #93441 (Sep 2009)


Related Topics



Leave a reply



Submit