Monitor PHP script processing

Asked

Viewed 1,316 times

5

Does anyone know a way to monitor PHP code processing and present to the client?

I’m designing a converter layout which takes data files in a given format and converts to another format.

Basically, I would like to present to the user (in the client browser), a progress bar with the evolution of the processing of the files on the server. This processing is not the progress of the upload (that I do with XMLHTTPRequest), but the progress of the conversion.

I’ve tried setting a cookie with setcookie and setrawcookie in PHP every 10% processed and trying to get the value of cookie with Javascript on the client side, also every 1 second with setInterval(), but it seems that PHP sends all cookies once after processing the script, and not at a time when setcookie() is called.

I also tried to use header() instead of setcookie and also the header sent only appear in the client after the complete processing of script. The start of the server processing I have done with XMLHTTPRequest to the page that does the processing.

I also tried with iframe, running the processing in iframe and trying to get cookies from it on the main page, but I was unsuccessful. I was able to monitor using a text file where php records progress and I read it through Ajax. However, it seems to only work with php safe thred

  • 1

    You can display a PHP service that returns only progress. Your client would access the URL to fetch the value.

  • Like this: the php script that does the conversion keeps saving the progress in a database or file on the server. The client keeps making requests for another script that keeps reading the progress of this database/ file?

  • I like to use Gearman for those things. http://br1.php.net/manual/en/gearmanclient.addtaskstatus.php

  • I didn’t. It also has this technique: http://rberaldo.com.br/server-push-long-polling-php-ios/

2 answers

2

It is possible to link a function to the event Progress of XMLHttpRequest, it is necessary to check if it is possible to calculate the size of the answer, which is received through the header "Content-Length".

In order for PHP to send the content during processing, it is necessary to call flush implicit, disconnect the buffer output and gzip compression. The settings I put on .htaccess cannot be modified with ini_set().


HTML/Javascript

<div id="progresso"></div>
<script>
var mensagem = document.getElementById('progresso');
var xhr = new XMLHttpRequest();
xhr.addEventListener('progress', function(e) {
    if (e.lengthComputable) { // é possível calcular progresso
        mensagem.textContent = parseInt(e.loaded / e.total * 100) + '% concluído';
    } else { // remove evento para não repetir chamada
        xhr.removeEventListener('progress', arguments.callee, false);
        mensagem.textContent = 'não é possível calcular progresso';
    }
}, false);
xhr.onreadystatechange = function(e) {
    if (this.readyState !== 4) return;
    if (this.status === 200) {
        alert('requisição concluída');
    } else {
        mensagem.textContent = 'erro';
    }
};
xhr.open('POST', 'progresso.php', true);
xhr.send();
</script>

.htaccess

php_value output_buffering Off

php progress.

<?php
// desligar compressão gzip
ini_set('zlib.output_compression', 'Off');
apache_setenv('no-gzip', 1); // apenas para Apache
// ativar flush implícito
ini_set('implicit_flush', 'On'); // ou ob_implicit_flush(1);

$length = 100; // etapas de processamento
header('Content-Length: ' . $length); // tamanho da resposta
for ($i = 0; $i <= $length; $i++) {
    // aguardar 0.2 segundos - simulando execução de tarefa
    usleep(200000);
    // exibir 1 caractere por tarefa concluída
    echo '.';
}

2

Following Rsinohara’s suggestion I was able to implement the logic using Xmlhttprequest, file_put_contents and file_get_contents.

The index.php file creates two Xmlhttprequest: one for the process.php file that does the data processing and saves the progress in Progress.txt (the code is only didactic) and another for Progress.php, which reads the progress of Progress.txt.

<!DOCTYPE html>
<!--
To change this license header, choose License Headers in Project Properties.
To change this template file, choose Tools | Templates
and open the template in the editor.
-->
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <script>
            function run(){
                var progressbar = document.getElementById('progresso');
                console.log('progressbar carregada');

                var xhr1 = new XMLHttpRequest();
                console.log('xhr1 criada');
                xhr1.onreadystatechange = function(){
                    console.log('xhr1: state=' + xhr1.readyState + ' status=' + xhr1.status);
                    if(xhr1.readyState == 4 && xhr1.status == 200){
                        console.log(xhr1.responseText);
                    }
                }
                xhr1.open('GET', 'process.php', true);
                console.log('xhr1.open');
                xhr1.send();
                console.log('xhr1.send');

                var xhr2 = new XMLHttpRequest();
                console.log('xhr2 criada');
                var progress = 0;
                xhr2.onreadystatechange = function(){
                    console.log('xhr2: state=' + xhr2.readyState + ' status=' + xhr2.status);
                    if(xhr2.readyState == 4 && xhr2.status == 200){
                        console.log('progresso: ' + xhr2.responseText);
                        progress = xhr2.responseText;
                        progressbar.value = progress;
                    }
                }

                while(progress < 100){
                    xhr2.open('GET', 'progress.php', false);
                    console.log('xhr2.open para progresso ' + progress);
                    xhr2.send();
                    console.log('xhr2.send para progresso ' + progress);
                }

            }
        </script>
    </head>
    <body>
        <button type="button" onclick="run()">Iniciar</button>
        <progress max="100" id="progresso" value="0"></progress>
    </body>
</html>

The process.php file (only didactic code)

<?php
ini_set('max_execution_time', '3600');

if(@file_exists('progress.txt')){
    @unlink('progress.txt');
}

for($i = 0; $i <= 100; $i += 20){
    sleep(3);
    file_put_contents('progress.txt', $i);
}
echo 'Terminou!';

Progress.php file

<?php

if(@file_exists('progress.txt')){
    echo file_get_contents('progress.txt');
}else{
    echo 0;
}
  • Apparently, in Windows, PHP Non Thread Safe does not work well with this. It sends the data all at the end. Already with PHP Thread Safe, it seems to work.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.