flush() is not working!

49 views
Skip to first unread message

offline...@googlemail.com

unread,
Mar 21, 2009, 7:01:58 AM3/21/09
to ZZEE PHPExe
I'm trying to print status-messages in a window from within a foreach
() loop via javascript:

foreach($_POST['files'] as $file){
$x++;
print "<script>parent.document.getElementById
('status').innerHTML='Datei $x von $anz ($file) wird
heruntergeladen...';</script>\n";
flush();

}

The message is only printed when the script is done, not while in
loop!
How can I make this work?

Paul (ZZEE)

unread,
Mar 21, 2009, 8:15:39 AM3/21/09
to php...@googlegroups.com
Hi,

There is a buffer in the built-in webbrowser of ZZEE PHPExe. Currently you
can not do anything about it, because on PHP side when you do flush() it
sends data immediately to the built-in browser, but the latter buffers
data.

This is in the todo list.

Perhaps you can change your application a little bit to avoid relying on
flush().

Paul.

offline...@googlemail.com

unread,
Mar 21, 2009, 11:54:50 AM3/21/09
to ZZEE PHPExe
How can I integrate a progress-meter like a bar or text, if flush()
isn't working??
The screen freezes while a script is running, not even a animated-gif
will work!

Paul (ZZEE)

unread,
Mar 21, 2009, 1:45:54 PM3/21/09
to php...@googlegroups.com
Try to display an animated gif, and then call a php script via ajax.

Or try a Flash progress bar.

Jill Arroway

unread,
Mar 22, 2009, 11:13:53 AM3/22/09
to php...@googlegroups.com
On 3/21/09, offline...@googlemail.com <offline...@googlemail.com> wrote:
>
> How can I integrate a progress-meter like a bar or text, if flush()
> isn't working?

You do this sort of thing client-side, not server-side. Javascript,
flash, AJAX, etc. - all of these techniques will work. You could even
just put one box inside another, with different background colors, and
then change the width in the inner one.

The client/server model inherent in web apps doesn't really have a way
of letting the client know the progress of the server. The server is
supposed to be kinda instant.

There are ways you could work around it. You could have the
client-side Javascript tick away a little timer function, make a fresh
"How are things going?" HTTP request on each tick, and update some
property of the GUI depending on the reply.

Generally speaking though, the rule is, only client-side code gets to
update the GUI. (The distinction may seem strange in PHPExe, where you
only have one machine, but it is still there).

Michael Graf

unread,
Mar 22, 2009, 1:17:42 PM3/22/09
to php...@googlegroups.com
Thanks for your answer, my only problem is, I need to update the progress while in a php foreach() loop :-(
And that doesn't seem to be possible with PHPexe....
I'm querying a mysql-db, fetch files over ftp and execute them via exec(), all within a foreach() loop.

By the way I'm not skilled enough in AJAX or FLASH to launch that kind of a campaign....

greetings, mike



2009/3/22 Jill Arroway <jilla...@googlemail.com>

Paul (ZZEE)

unread,
Mar 23, 2009, 8:05:49 AM3/23/09
to php...@googlegroups.com
(The distinction may seem strange in PHPExe, where you
> only have one machine, but it is still there).

The distinction is simple: client side is Javascript, server side is PHP
:)

Paul (ZZEE)

unread,
Mar 23, 2009, 8:13:29 AM3/23/09
to php...@googlegroups.com

> Thanks for your answer, my only problem is, I need to update the
> progress
> while in a php foreach() loop :-(
> And that doesn't seem to be possible with PHPexe....
> I'm querying a mysql-db, fetch files over ftp and execute them via
> exec(),
> all within a foreach() loop.

You can move it to Javascript: get a mysql-db query via PHP, results via
AJAX / JSON to Javascript, then do a loop in Javascript, then call a PHP
script via AJAX to run exec(), then update your UI via Javascript.

> By the way I'm not skilled enough in AJAX or FLASH to launch that kind
> of a
> campaign....

AJAX is a trivial thing, you can learn it a couple of minutes. There are
lots of frameworks as well.

http://en.wikipedia.org/wiki/Ajax_(programming)

Gert

unread,
Mar 23, 2009, 10:30:38 AM3/23/09
to ZZEE PHPExe
Hi Paul,

There are (nearly always) several options to implement a specific
program logic, but for me the whole discussion is not very
satisfyingly. Fact is that the requested logic doesn't work on ZPE
while it works well on a local server and a browser, so it's a problem
caused by ZPE. Thus ZPE should be improved as soon as possible and not
the user should open a new project like learning and programming AJAX.

Gert

Paul (ZZEE)

unread,
Mar 23, 2009, 12:06:51 PM3/23/09
to php...@googlegroups.com

This flush() support is in the todo list and we will try to fix it.

Jill Arroway

unread,
Mar 23, 2009, 1:42:42 PM3/23/09
to php...@googlegroups.com
Not knowing your project, this suggestion may not be helpful ... in
which case I apologise ... but, have you considered not using PHPExe
at all for this one? I mean, just use plain PHP, and then run it from
the command line with

php -q <filename.php>

and then you'll get all your printfs coming out on the command prompt
window right away.

Just a thought.

Paul (ZZEE)

unread,
Apr 15, 2009, 8:20:00 PM4/15/09
to php...@googlegroups.com
Hi guys,

The new version 2.4 has an experimental support for "no buffering" mode.

To turn it on, do this Javascript code first:

external.buffering = false;

Please test and let me know if it works for you.

If you want to turn the buffering back on, do:

external.buffering = true;

Michael Graf

unread,
Apr 16, 2009, 8:33:36 AM4/16/09
to php...@googlegroups.com
Hi Paul,

it doesn't seem to work as expected :-(
I have to add an alert('') event to every cycle of the loop, otherwise the screen is not updated.
Can't you just make it work like on a real webserver like apache??
The flush() statement is very important to let the user know whats happening while the program works!


2009/4/16 Paul (ZZEE) <gro...@zzee.com>

Paul (ZZEE)

unread,
Apr 16, 2009, 8:58:29 AM4/16/09
to php...@googlegroups.com
> Hi Paul,
> it doesn't seem to work as expected :-(
> I have to add an alert('') event to every cycle of the loop, otherwise
> the
> screen is not updated.
> Can't you just make it work like on a real webserver like apache??
> The flush() statement is very important to let the user know whats
> happening
> while the program works!

Hmm... in our tests it worked as in Apache. Maybe I was not clear enough.
You need to do

external.buffering = false;

*before* a PHP script you want to update a progress bar is launched.

For example, the first screen is a kind of entry, a main form, and the
second one does some lengthy job, during which you want to keep your user
updated. So in this example, you need to set external.buffering to false
on the first screen, so before the second screen runs this flag has
already been set. That is, the first screen needs to have
<script type="text/javascript">
external.buffering = false;
</script>

If you still can't make it work, can you make a simple example that
illustrates your problem and send its source code over to support at zzee
dot com?

Michael Graf

unread,
Apr 16, 2009, 9:25:43 AM4/16/09
to php...@googlegroups.com
I have 2 files. The 1. is a login-form where a set "external.buffering = false;"
The 2. is the main window where the user can select files to download and install on their system.

Following Code is not working:

foreach($_POST['files'] as $file){
$nr = $x + 1;
print "<script>document.getElementById('status').innerHTML='Loading File $nr of $anz ...'</script>\n";
flush();
$x++;
ftp_get($ftp,$file,$file,FTP_BINARY);
system($file." /verysilent");
unlink($file);
}



2009/4/16 Paul (ZZEE) <gro...@zzee.com>

Paul (ZZEE)

unread,
Apr 16, 2009, 11:59:00 AM4/16/09
to php...@googlegroups.com
Michael,

The following example works for me fine (basically I replaced ftp stuff
with sleep() in your example). What is your OS and webbrowser?

========================================

<div id="status">abc</div>
<?php
$x = array('file1', 'file2' , 'file3');
foreach($x as $file) {


print "<script>document.getElementById('status').innerHTML='Loading File

$file'</script>\n";
flush();
sleep(3);
}
echo
"<script>document.getElementById('status').innerHTML='Done';</script>";
?>

Michael Graf

unread,
Apr 16, 2009, 12:06:03 PM4/16/09
to php...@googlegroups.com
We use windows xp (sp3) with internet-explorer 7.
Is it possible, that the ftp-download or the external system() call prevents the screen from updating?
The screen kind of locks till the foreach-loop is finished.



2009/4/16 Paul (ZZEE) <gro...@zzee.com>

Paul (ZZEE)

unread,
Apr 16, 2009, 1:27:32 PM4/16/09
to php...@googlegroups.com
I tested it on Vista + IE7 and XP + IE6 both were fine.

I recommend that you use more correct syntax, in particular, add
type=\"text/javascript\" into the <script> tag, like in the example below.

Try to compile my example, does it work for you?


=======================================================================

<div id="status">abc</div>
<?php

$x = array('http://www.google.com', 'http://www.yahoo.com' ,
'http://www.cnn.com');
foreach($x as $file) {
echo "<script
type=\"text/javascript\">document.getElementById('status').innerHTML='Getting
$file';</script>\n";
@flush();
sleep(3);
//file_get_contents($file);
}
echo "<script
type=\"text/javascript\">document.getElementById('status').innerHTML='Done';</script>";
?>

Michael Graf

unread,
Apr 16, 2009, 1:38:23 PM4/16/09
to php...@googlegroups.com
I checked the same script on my debian machine and everything works like expected. So the problem must be within phpexe.
The flush() does not do exactly what apache2 does, empty cache and send all output to the browser.



2009/4/16 Michael Graf <offline...@googlemail.com>

Paul (ZZEE)

unread,
Apr 19, 2009, 3:28:05 PM4/19/09
to php...@googlegroups.com
I put a sample to the site consisting of two files. This sample downloads
websites, and shows how to use flush().

http://www.zzee.com/phpexe/flush.zip

It works OK on all test computers.

In short, I recommend that you use both flush() and ob_flush() to update
the screen. Below is these two files:

index.php
=======================================
<html>
<head>
</head>
<body>

<script type="text/javascript">
// This is what needs to turn ZPE into a non buffering mode
external.buffering = false;
</script>

<h2>Flush() Test</h2>

<form action="buffering.php" method="post">
URLs to download:
<br/><textarea name="files" style="width: 90%; height:
200px;">http://google.com
http://yahoo.com
http://microsoft.com
http://facebook.com
http://en.wikipedia.org
</textarea>
<br/><input type="checkbox" name="doActualFile" value="1"
checked="checked"/>
Download URLs? (otherwise just sleep() is called)
<br/><input type="submit" value="Go" />
</form>

</body>
</html>
=======================================


buffering.php
=======================================
<?php
$getActualFile = isset($_REQUEST['doActualFile']) ?
($_REQUEST['doActualFile'] + 0) : 0;
$files = $_REQUEST['files'];
$files = preg_split('/\r?\n/', $files);
?>
<div id="status">Progress information...</div>
<script type="text/javascript">
var s = document.getElementById("status");
function updateStatus(text) {
s.innerHTML = text;
}
</script>
<?php
foreach($files as $file) {
if ($file == '') { continue; }
showProgressInfo("Getting " . $file);
if ($getActualFile) {
@file_get_contents($file);
} else {
sleep(3);
}
}
showProgressInfo("Done");

// After you are done with the progress it is better to turn the buffering
mode on:
echo <<<ABCDEF
<script type="text/javascript">
external.buffering = true;
</script>
ABCDEF;

function showProgressInfo($text)
{
echo "<script
type=\"text/javascript\">updateStatus(\"$text\");</script>\n";

// Just in case we send 256 bytes of output
// If no updating happens, uncomment this block
/*for ($i = 0; $i < 32; $i++) {
echo "<!-- -->";
}*/

// Do both flush and ob_flush
@flush();
@ob_flush();
}
?>
=======================================

Paul (ZZEE)

unread,
Apr 19, 2009, 3:29:12 PM4/19/09
to php...@googlegroups.com
> The flush() does not do exactly what apache2 does, empty cache and send
> all
> output to the browser.

I recommend that you use both flush() and ob_flush(), please see my
example. Compile the example on your computer and let me know.

shimax

unread,
Apr 19, 2009, 5:52:41 PM4/19/09
to ZZEE PHPExe
Hello Paul,

I am not the original questioner but
your example works perfectly on my computer as well.

This example is very helpful and interesting.

Paul (ZZEE)

unread,
Apr 20, 2009, 12:28:32 PM4/20/09
to php...@googlegroups.com
Thanks for the feedback!

If anyone has problems with the sample, please let me know.

Paul (ZZEE)

unread,
May 1, 2009, 8:36:36 AM5/1/09
to php...@googlegroups.com
Hi,

Have you been able to make it work? Have you compiled my sample?

Michael Graf

unread,
May 1, 2009, 2:37:54 PM5/1/09
to php...@googlegroups.com
we used a different approach by using a JS-Loop and call the php-script within the loop

we were not able to get your example working.....no screenupdates over the runtime of the script, just the last value when the script is exiting :-(


2009/5/1 Paul (ZZEE) <gro...@zzee.com>

Paul (ZZEE)

unread,
May 1, 2009, 5:23:42 PM5/1/09
to php...@googlegroups.com
Michael,

> we used a different approach by using a JS-Loop and call the php-script
> within the loop

You need to put

<script type="text/javascript">
external.buffering = false;
</script>

one step earlier, before this script with a JS loop runs, i.e. this
javascript code should have been executed in the previous URL.

> we were not able to get your example working.....no screenupdates over
> the
> runtime of the script, just the last value when the script is exiting
> :-(

Have you compiled the example intact? Please confirn whether this example
works for you if compiled intact. Also you can replace there http: URLs
there by ftp: to see how ftp works as well (right in the textarea box on
the first page).

Reply all
Reply to author
Forward
0 new messages