Time Intensive PHP Script & Client Progress Bar - How Would You Do it?

Associate
Joined
23 Oct 2002
Posts
1,525
Location
That London, née Brighton
Since making my original thread I've tried several ways of achieving my goal and can't get it to work, so I'm wondering what other methods you guys might suggest.

Assume a php process which takes 45+ seconds to run, maybe more.
We want to launch this process on the web server, from a browser, somehow.
We also want the browser to be updated with the progress of the process (it's scanning other sites so overall time will vary with each execution) so the client isn't left sat staring at an empty page and so the browser itself doesn't timeout.

How would you do it?

Things that don't work
1. I have permission to exec() but can't invoke php scripts via it, for some odd reason
2. Firing the request to start the scan via ajax, and then requesting the progress update(s) via ajax, doesn't work in internet exploder because it won't do anything else net related while it's waiting for the first (45+ seconds) script to return
 
Soldato
Joined
27 Sep 2005
Posts
4,622
Location
London innit
The original http request would be blocking, so you'd want a fire and forget request that returns a request id quickly, then client side ajax calls to a status update thingy at regular intervals.

Javascript on the browser is a pain as there's no sleep statements - so the update thingy should have sleep(60) in it, otherwise you'll spike CPU.

Edit: You'll need to figure out why exec isn't working, or run a cronjob or something.
 
Associate
OP
Joined
23 Oct 2002
Posts
1,525
Location
That London, née Brighton
It's this original fire and forget thing that the browsers just don't seem capable of forgetting. Or, well, iexplore doesn't anyway. I even tried issuing a header('Location:'); redirect in the initial scanner php, just before it starts scanning, and flush() and such, but the browser still waited 20 seconds before even doing anything with that. Very weird and annoying.
 
Associate
OP
Joined
23 Oct 2002
Posts
1,525
Location
That London, née Brighton
Ok it works in firefox. Here comes the big moment...

Nope iexplore still just waits for the iframe to load. Next stage then is try and make the iframe make an ajax request then the main window make an ajax request...
 
Last edited:
Associate
Joined
3 Jun 2008
Posts
411
it should work in non prehistoric versions of IE. Just to be clear your iframe output should be like this.

echo "<script>parent.update_progress_function('10');</script>";
flush();
echo "<script>parent.update_progress_function('20');</script>";
flush();
 
Soldato
Joined
27 Sep 2005
Posts
4,622
Location
London innit
It's this original fire and forget thing that the browsers just don't seem capable of forgetting. Or, well, iexplore doesn't anyway. I even tried issuing a header('Location:'); redirect in the initial scanner php, just before it starts scanning, and flush() and such, but the browser still waited 20 seconds before even doing anything with that. Very weird and annoying.

The initial request should just return a unique id very quickly and end. No redirects, just finish. Ajax has to do the rest.
 
Associate
OP
Joined
23 Oct 2002
Posts
1,525
Location
That London, née Brighton
I guess then that by "initial request" you don't mean my initial request that causes the scan to take place? That request won't see a response for 40+ seconds. I'm considering this idea of trying to flush() some javascript after each iteration of the loop but I know apache tends to cache stuff anyway regardless of what php tries to do, so I'm not holding my breath ._.
 
Associate
Joined
3 Jun 2008
Posts
411
Apache wont cache anything unless you have gzipping on.

you can use ob_end_flush(); at the start of your script to stop buffering and flush if you hare having problems. At least with HTML5 we will have proper sockets. woot.

Here is a test script for you.

<html>
<body>
This page is loading.<br />
<?php ob_flush(); sleep(10); ?>
Almost there...<br />
<?php ob_flush(); flush(); sleep(10); ?>
Done.<br />
</body>
</html>
 
Associate
OP
Joined
23 Oct 2002
Posts
1,525
Location
That London, née Brighton
Still getting buffered :(

I've modified my loop (which presently scans 112 pages) to send this after each page gets scanned

PHP:
print '<script type="text/javascript">parent.derp('.$i.');</script>';
flush();

which gets sent into the iframe. derp is a function in the parent which just alerts the variable passed.

Lo and behold, it does nothing for 40+ seconds then starts alerting numbers 1 through 112.

I'm tearing my hair out with this now ._.

P.S. using fiddler2 I can see it's not being gzip encoded, either
 
Last edited:
Associate
Joined
3 Jun 2008
Posts
411
ob_end_flush();
echo '<script type="text/javascript">parent.derp('.$i.');</script>';
ob_flush(); flush();
echo '<script type="text/javascript">parent.derp('.$i.');</script>';
ob_flush(); flush();

still no dice?
 
Associate
OP
Joined
23 Oct 2002
Posts
1,525
Location
That London, née Brighton
Still no dice :(

Also, now I look at it in Fiddler and t's saying it is gzip encoded. Seems I was mistaken last night. So trying to disable this now. Have tried:

1. using modified php.ini in my own directory (I know this gets read) with "zlib.output_compression = Off" in it
2. .htaccess in there with "SetEnv no-gzip dont-vary" and "RewriteRule . - [E=no-gzip:1]" in it
3. using the exact php you've pasted

and still gzipping :(
 
Last edited:
Soldato
Joined
27 Sep 2005
Posts
4,622
Location
London innit
I guess then that by "initial request" you don't mean my initial request that causes the scan to take place? That request won't see a response for 40+ seconds. I'm considering this idea of trying to flush() some javascript after each iteration of the loop but I know apache tends to cache stuff anyway regardless of what php tries to do, so I'm not holding my breath ._.

No. Your initial request to the webserver should trigger a second process to start scanning. The initial request returns a unique id relating to the scan as soon as the scan is initiated.

The browser then uses this unique id to poll the state of the scan, asking if it's ready every 5 seconds or something. When the scan is complete the server will reply that the scan is done and trigger the browser to display the results.

You need at the very least to be able to exec shell commands from the server, more robust is to use a message queue.
 
Associate
OP
Joined
23 Oct 2002
Posts
1,525
Location
That London, née Brighton
Ah yes, well, this was my original model, but trying to do exec(); with php scripts didn't work, and pcntl_fork isn't compiled in, so unless I keep bothering the host (vidahost, they're good at support usuall) about this, it looks like I may not get very far.
 

Izi

Izi

Soldato
Joined
9 Dec 2007
Posts
2,718
does it need to be a progress bar?

just do it with jquery ajax. on ajax request show waiting.gif on complete hide waiting.gif and show done.gif?
 
Associate
Joined
3 Jun 2008
Posts
411
OP said 45+ seconds to run so I would suggest showing progress. I have a hosting account at no-wires.co.uk and can confirm no problems flushing the buffer.
 
Associate
Joined
26 Oct 2008
Posts
141
If you must have a progress bar, would it be possible to have some AJAX that calls the PHP script including a start and end position (or the search position could be saved in a cookie?).
So Your AJAX would call the PHP to do one section of work at a time - after each section your JavaScript will save the results found so far and show the progress to the user. :cool:

Otherwise you could just have a 45 second loading.gif as mentioned above ;)
 
Associate
OP
Joined
23 Oct 2002
Posts
1,525
Location
That London, née Brighton
Nice idea with doing it incrementally... obviously makes it a bit flakier and such but, hrm, interesting idea...

Am also trying posting on vidahost's forums about the exec() issue, see if anyone else has resolved it, as if they have, it's all fine and sorted
 
Back
Top Bottom