Monitor PHP script processing

5

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

I'm designing a layout converter that takes data files in a certain format and converts them 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 upload (this is done with XMLHTTPRequest ), but the progress of the conversion.

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

I've also tried to use header() instead of setcookie and also the sent header only appear on the client after full script processing. The beginning of the processing on the server I have done with XMLHTTPRequest for the page that does the processing.

I also tried with iframe, causing the rendering to run in the iframe and trying to get its cookies from the main page, but I was not successful. I was able to monitor using a text file where php writes progress and read it through Ajax. However, it only seems to work with php safe thred

    
asked by anonymous 26.06.2015 / 16:49

2 answers

2

Following the suggestion of RSinohara I was able to implement 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 processing of the data and saves the progress in progress.txt (the code is just didactic) and another for progress.php, which reads the progress of the 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 file process.php (code only didactic)

<?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;
}
    
26.06.2015 / 20:15
2

It is possible to link a function to the progress event of XMLHttpRequest , in which it is necessary to check if it is possible to calculate the response size, which is received through the Content- .

In order for PHP to be able to send content during processing, you need to turn on flush , shut down the output and gzip compression. Settings I put in .htaccess can not be changed 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

progress.php

<?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 '.';
}
    
07.08.2015 / 20:33