Read the entire stream in real time in the stream

Note: this post has a difference with this post, whose accepted answer just read every time line.

I need to crop 3D models for 3D printing on the server side, the process will cost some time. So I have to show the process to the user, I use redis to store the process. I want to update the process every 0.5 seconds. For example, sleep 0.5 seconds, read all the contents in a pip and process it every time.

At the moment, I tried the following two, the first one will hold on until it runs out. the second use is not yet the right way, it will continue to write redis, which will cause the request to read the client to be completed to the end.

I tried these two:

The first will be held until the completion of the team.

$descriptorspec = array(
    0 => array("pipe", "r"),
    1 => array("pipe", "w"),
    2 => array("pipe", "w")    //here curaengine log all the info into stderror
);
$command = './CuraEngine slice -p -j ' . $fdmprinterpath . ' -j ' . $configpath . ' -o ' . $gcodepath . ' -l ' . $tempstlpath;
$cwd = '/usr/local/curaengine';
$process = proc_open($command, $descriptorspec, $pipes, $cwd);
if(is_resource($process))
{
    print stream_get_contents($pipes[1]);  //This will hold until the command finished.
}

, , .

  $descriptorspec = array(
        0 => array("pipe", "r"),
        1 => array("pipe", "w"),
        2 => array("pipe", "w")    //here curaengine log all the info into stderror
    );
    $command = './CuraEngine slice -p -j ' . $fdmprinterpath . ' -j ' . $configpath . ' -o ' . $gcodepath . ' -l ' . $tempstlpath;
    $cwd = '/usr/local/curaengine';
    $process = proc_open($command, $descriptorspec, $pipes, $cwd);
    if(is_resource($process))
    {
        while ($s = fgets($pipes[1])) {
            print $s;
            flush();
        }
    }
+4
3

fread() fgets().

0

Symfony Process. , , . :

$process = new Process($command);
$process->start('processOutput');

while ($process->isRunning()) {
    usleep(500000);
    $progress = $process->getIncrementalOutput();
    progressOutput($progress);
}

$output = $process->getOutput();

//
// Example implementations:
//
function progressOutput($progress) {        
    echo $progress;
    ob_flush();
}

function processOutput($type, $output) {
    if ($type == Process::OUT) {
        echo $output;
        ob_flush();
    }
}
+1

, :

while(@ob_end_clean());

.

, . , , , , Chromium, Firefox.

, , fgets() fread(), . , XMLHttpRequest.

, Chromium:

<?php
//stream.php

//disable output buffering
while(@ob_end_clean());
ob_implicit_flush(true);

if(empty($_SERVER['QUERY_STRING'])){
    //simulate a lengthy process
    file_put_contents(__FILE__.'.txt',$z='');
    for($i=0; $i<10; $i++){
        sleep(1);
        echo $s = "<div>{$i}</div>\n";
        file_put_contents(__FILE__.'.txt',$z.=$s);
    }
}else{
    //delay 500ms
    usleep(500000);
    echo file_get_contents(__FILE__.'.txt');
}

HTML- :

<!DOCTYPE html>
<html>
<head><meta name="viewport" content="width=device-width, initial-scale=1" charset="utf-8"></head>
<body>
<div id='stream'></div>
<script>
var active = true;
xhr('/stream.php',function(){ active = false; });
update();

function update(r){
    if(r) document.getElementById('stream').innerHTML = r.responseText;
    if(active) xhr('/stream.php?stream',update);
}

function xhr(url,callback){
    var r = new XMLHttpRequest();
    r.open('GET',url);
    r.onreadystatechange = function(){ if(r.readyState==4) callback(r); };
    r.send();
}
</script>
</body>
</html>

, .

+1

Source: https://habr.com/ru/post/1664369/


All Articles