Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi programmers, I have a cgi script that posts data to another cgi script that processes this information and emails the appropriate recipients. Often these emails can take time and I am wanting to output information while the script processes this information (eg a progress bar, or rotating image). I am using apache as the web server. I have tried to flush output buffers with no success. I have also read that this is often a problem with only the whole page being displayed once the script has finished processing. What would be a solution to this problem? Thankyou as always ..

Replies are listed 'Best First'.
Re: CGI progress indicator
by davidrw (Prior) on Aug 25, 2005 at 12:58 UTC
Re: CGI progress indicator
by anonymized user 468275 (Curate) on Aug 25, 2005 at 13:55 UTC
    Instead of making the user wait for the emails to finish, why not start a detached process to do the mailing and let the user go and look at the progress on a separate page ... or not, as, if and when he wants to review that progress. The detached program could record its progress in a file loaded up by the page where he can review that progress.

    Update: Of course, even users expect that even when mail is sent it takes time to be received anyway. The delay between sending and receiving is all the user sees, so why bother to take your part of it out of the closet? It was only the making the user wait instead of detaching that made it seem (temporarily) attractive to do so.

    One world, one people

      I'd like to add a bit to this idea. I used it once in a project, and it worked just fine. But I cant remember the exact method that I used.

      EDIT: I might have mistaken ... The problem with starting a new process is that you can do that while working under CGI. Maybe I'm wrong? You cant use fork/system or similar as they block the execution of your script - and threads are usually not "compiled in" for CGI usage. And even if they were, what happens to child's if parent ends itself.

      The idea is that you actually (re)generate page every few seconds - in your case, you may put it inside of loop that is sending the emails and make it print something like : "Sent X emails out of Y". Or calculate how much email have you sent in %. Something like : $percentage = (100 * $sent) / $total_emails ... and then generate a table (html table) where you set bgcolor and it's width=$percentage. I hope it's clear - if not, I can try to explain a little better.

      You then save that output as HTML file, say progress.html and refresh it every 2, 3, 5 ... seconds by using meta refresh in it's head.

      The only question is how to get the browser to load that page. Plain redirect (by header) wont do it, as browser will wait for your script to finish loading. If I recall right (I lost original project code) I did it with JavaScript. Just output something like following by your script and it should redirect the browser (if it has java enabled) as soon as it receives that part of the page.

      <html><head><title>Blabla</title></head> <body> <script language="JavaScript"> location = "http://your-site.com/progress/html"; </script>

Re: CGI progress indicator
by Anonymous Monk on Aug 26, 2005 at 12:29 UTC
    Thanks for your comments. If I was wanting to display an html page while another process handles the mailing task, how could I achieve this? As stated I am posting the data to another cgi script. Should I look into spawning another a child process. Or would this still result in the whole cgi script requiring to be processed before data can be displayed. I looked at redirecting, but again the script must compile first. Thanks
      i've dealt with something similar to this in the past, however it was a server downloading files instead of sending out emails.

      once the user submits, just simply fork off your mailing process (giving it all the info it needs... to, from, message etc.) This should run in the background while the browser is redirected to your CGI progress page, thus not causing your webpage to hang while emails are being sent.

      In my case i just made a command line script that was set to take in command line arguments. i think i implimented it by just using an exec(ftp_dl <arguments>). So i'm not sure how you might impliment this using exclusively webpages.