Continue Processing PHP After Sending Http Response

How to continue PHP script after sending HTTP response

In JS:

$(document).ajaxSuccess(function ( event, xhr, settings) {
if(xhr.status === 202) {
//console.log("Your file is in process");
//console.log(xhr.responseJSON);
//Activate interval to check if file is ready
}
});
//Make petition
$.post("petitionsHandler.php", {"texto":"Hello world, greeting from México!"}, function (resp){
//Handle responses
}, "json").fail(function () {
//Handle errors
});

In PHP

<?php
$text = $_POST["text"];
//If you are using sessions don't forget to close the session file
//Or such will be blocked until long script finishes
session_write_close();
header("HTTP/1.1 202 Solicitud recibida"); #This is the code I wanted to send
header("Content-Type: application/json"); #Depends the kind of data you're sending to the client
// Buffer all upcoming output...
ob_start();

// Send your response.
echo '{"success":true, "message":"Your request has been received."}';
// Get the size of the output.
$size = ob_get_length();

// Disable compression (in case content length is compressed).
//header("Content-Encoding: none"); #I didn't need this but check your situation

// Set the content length of the response.
header("Content-Length: {$size}");

// Close the connection.
header("Connection: close");

// Flush all output.
ob_end_flush();
ob_flush();
flush();
//All outputs have now been sent to the client
//You can continue executing your long tasks

include_once('createExcel.php');

createExcel.php

<?php
sleep(10); #You can use to checkthat the code works
//The above code will respond the client immediately and after ten seconds the Excel file will be created
require "PHPSpreadSheet/vendor/autoload.php";
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet->setCellValue('A1', $text);
$writer = new Xlsx($spreadsheet);
$writer->save('MyFile.xlsx');

Of course you have to make validations, so you don't have lots of running process in background but I hope the general idea has been shown in this example.

This is not exactly the code I use, but this is all it takes to continue executing code after responding the client.

In my own opinion, I thinks this is better than using exec() or similar functions which invoke the command terminal as that could be a potential vulnerability , so you don't have to change permissions or anything.

Note: If you're using sessions, Please remember to use session_write_close() because on heavy tasks will block the file until such task is finished.

I hope it helps :)

My answer was based on this blog: https://qastack.mx/programming/15273570/continue-processing-php-after-sending-http-response

Continue PHP execution after sending HTTP response

Have the script that handles the initial request create an entry in a processing queue, and then immediately return. Then, create a separate process (via cron maybe) that regularly runs whatever jobs are pending in the queue.

PHP with AJAX - Continue Processing After Sending Response to the User

It looks like (as @ADyson said in the comment) flushing output doesn't seem work with AJAX. So, the only solution to the problem is to use Cron Job. To do this, I used PHP Cron Scheduler. But crontab can be used directly to add a Cron Job to the list.

I added the post processes to another PHP file with suitable changes so that it can do the same tasks from the script and added the file to the Scheduler.

This solution may seem a real pain, but there is no solution to this problem other than using Cron Job.

Send response and continue executing script - PHP

You can try something like this.

ignore_user_abort(true);
set_time_limit(0);

ob_start();
// do initial processing here
echo $response; // send the response
header('Connection: close');
header('Content-Length: '.ob_get_length());
ob_end_flush();
ob_flush();
flush();

// now the request is sent to the browser, but the script is still running
// so, you can continue...

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);
?>


Related Topics



Leave a reply



Submit