Output JSON responses through JQUERY in real-time whilst processing PHP script

Hi guys,

I need help with my issue of not being able to output JSON responses in real-time using JQUERY whilst PHP calls an external command line script.

Firstly, I’m using this JQUERY AJAX file upload with progress bar example to handle the file upload. So here you can pretty much see my coding for that mechanism. Although I added “dataType: ‘json’” to the options to handle the response.

In the PHP script, I handle the file upload, clean up the file name, etc. Then I call an external cmd process. This process throws out updates such as “Completed: 10%”, through to “Completed: 100%”. This is the info that I wanna throw out to the browser via json. Here is my code for this:

ob_implicit_flush(true);
ob_end_flush();

$cmd = //call exe with arguements

$descriptorspec = array(
    0 => array("pipe", "r"),
    1 => array("pipe", "w"),
    2 => array("pipe", "w")
);
flush();
$process = proc_open($cmd, $descriptorspec, $pipes, NULL, NULL);
if (is_resource($process)) {
    $return = array();
    while ($s = fgets($pipes[1])) {
        $return['status'] = substr($s,0,16);
        echo json_encode($return);
        //file_put_contents($file, json_encode($return));
        flush();
    }
}      
proc_close($process);

This throws out this json output:

{"status":"Completed: 10%\r\n"}
{"status":"Completed: 13%\r\n"}
{"status":"Completed: 16%\r\n"}
... truncated ...
{"status":"Completed: 90%\r\n"}
{"status":"Completed: 95%\r\n"}
{"status":"Completed: 100%\r","output":"<p><img src=\"images\/accept.png\" width=\"16\" height=\"16\" alt=\"\" valign=\"top\" \/> Successfully converted:<br \/><br \/><a href=\"test.zip\">test.zip<\/a><\/p>"}

So, I want to be able to output the status values every 2/3 seconds. The final output value is outputted in the JQUERY success function.

Please bear in mind, I’m a lightweight user of JQUERY and AJAX.

The alternate route would be for me to write the status message(s) to a unique txt file and have JQUERY poll that every few seconds.

Thanks

This is a rather tricky task.
The main problem here is that PHP can’t send anything to the browser until script is completely finished.
If you want to get it work in “real time” you have two options:

  1. Use web sockets (with some library like Ratchet);

  2. Emulate real time using periodic requests.

Let me explain what second option means. When you’re sending a file to the server with jQuery, you can set an interval to run some code which will make requests to the temporary file:

//jQuery:
sendFile();

var interval = setInterval(function(){
    $.get('tempfile.txt', {}, function(content){ 
        console.log(content);
        if (content == '100%') { 
            clearInterval(interval);
        }
    });
}, 500);

That code will read contents of tempfile.txt each 500 milliseconds, until there is not string “100%”.
At the same time, on the server side, your PHP script can update contents of that file inside the loop:

while ($s = fgets($pipes[1])) {
    $percentsDone = getPercentsFrom($s);
    file_put_contents('tempfile.txt', $percentsDone);
}

To make this support multiple requests, file name should be unique every time. That can be achieved if, for example, you’ll add session_id() and timestamp to the name of file.

UPD: just realised you’re talking about the same in the last line of your post :smiley: sorry then, If I wrote obvious things here

Thanks for your input. I did go down the txt file route. So on the default page, I have PHP generate a unique text file name, apply that to a hidden input form field, then pass that through post into the submit page. There I create this unique text file and use file_put_contents (ensures I only have one line of text to read) to save the status message in the text file. So back in the default page, I had Jquery perform a get function every 2 seconds on the unique text file. Once Jquery gets the success response, I stopped the get function interval and deleted the text file. Works well.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.