Eoin Redmond has asked for the wisdom of the Perl Monks concerning the following question:

I have written a file upload routine (Win32) using PERL (thanks to some helpful monks) which works fine but I would like to enhance it by including a progress indicator bar (or something similar) so I can view the upload progress of the file.

The problem I have is that the PERL program which uploads the file does not display the resultant web page until the file has been uploaded even though my program builds virtually all of the web-page before performing the file upload. This is a problem when uploading a file which takes say 15 mins i.e. I'm left with a blank screen until the upload is complete and the resultant web page is displayed.

This is preventing me from adding code which would indicate the on-going status of the file upload.

I'd be grateful if anybody could offer any suggestions

Thanks

Eoin

Replies are listed 'Best First'.
Re: About how PERL scripts execute
by ajt (Prior) on Feb 09, 2003 at 21:40 UTC

    Eoin

    Your problem isn't really Perl, rather CGI. The way that CGI is designed means you can't send progress data back while the upload is in progress. See the following node: "Yet another progress bar." for some additional comments and ideas - it's a popular question, but the answer is hard...

    Good luck!


    --
    ajt

      Thanks ajt

      I'm hoping Macphisto will see my post and get in contact with me. I'd be interested to see if he came up with a workable solution

      Obviously, I'm new to Perl and this site and I was wondering is there a way to contact Macphisto directly instead of just hoping he will see my post?

      Thanks again

      Eoin

        You can send Macphisto a private message by using the /msg command in the chatterbox. Whenever Macphisto nexts visits the Monastery, the message will be waiting. See Using the Chatterbox: Private Messaging for more information.


        Just a tongue-tied, twisted, earth-bound misfit. -- Pink Floyd

Re: About how PERL scripts execute
by jacques (Priest) on Feb 09, 2003 at 22:25 UTC
    The problem I have is that the PERL program which uploads the file does not display the resultant web page until the file has been uploaded even though my program builds virtually all of the web-page before performing the file upload.

    Did you remember to flush (the buffer)?

    Try putting this near the top of your program: $|++;

    Also see the perldoc flush/unbuffer information.

    (P.S. It's Perl, not PERL.)

Re: About how PERL scripts execute
by Wysardry (Pilgrim) on Feb 10, 2003 at 02:03 UTC

    Try the CGI::Push or CGI modules.

    Ignore the text that says it doesn't work in Internet Explorer, as that's out of date. Links 2 from Gossamer Threads uses nph (non parsed header) scripts to show the progress of the pages it builds, and that works fine in IE5 on an NT4 system with either Apache or PWS and ActivePerl.

    It might help to take a peek at the code for that too (check the files that start with "nph-").

    __________
    "Every program has at least one bug and can be shortened by at least one instruction -- from which, by induction, one can deduce that every program can be reduced to one instruction which doesn't work." -- (Author Unknown)

Re: About how PERL scripts execute
by steves (Curate) on Feb 09, 2003 at 23:46 UTC

    I've gotten this sort of thing to work on most browsers at work by making sure STDOUT is automatically flushed and then having my long running upload CGI use an alarm signal catcher to periodically print a progress character.

      Thanks for the note Steve

      Do you think you could give me an example of an alarm signal catcher?. I'm new to Perl and after looking at the alarm function I see that it would simply kill my CGI after a certain period of time

      I'm assuming you wrote some code as a kind of wrapper for alarm?

      Thanks

      Eoin

Re: About how PERL scripts execute
by Coruscate (Sexton) on Feb 10, 2003 at 09:09 UTC

    If my name were merlyn, I might say that "I" have a column that might help with this. If you take the code from that column and understand it enough, you could make this work for you. The most basic principle here would be to fork() a separate process. The parent could do the progress, while the child would handle the upload. I might just whip up a script to do just that (if I can find the time).


    If the above content is missing any vital points or you feel that any of the information is misleading, incorrect or irrelevant, please feel free to downvote the post. At the same time, reply to this node or /msg me to tell me what is wrong with the post, so that I may update the node to the best of my ability. If you do not inform me as to why the post deserved a downvote, your vote does not have any significance and will be disregarded.

      Coruscate

      Thanks for your response - all help is much appreciated by this Perl novice

      I looked at merlyn's column and while I'd be lying if I said I understood every line in his code, I do get the general idea and it seems to offer a solution to the other problem I have which is IIS eventually timing out on a large file upload

      Obviously it would be great if you have the time to whip up some code though if not I can try and adapt his code for my application and environment

      Thanks

      Eoin

Re: About how PERL scripts execute
by Macphisto (Hermit) on Feb 10, 2003 at 20:20 UTC
    I ended up having to use a wee bit of Javascript to get this going. Firstly, I was doing it in mod_perl, so I don't know how well it'll translate into your project, but hopefully it'll help.

    Each user that logged in got a 10 digit alphanumberic session ID ( $session_id ) associated with him and passed around as part of his cookie. I also had Apache::Request spool to a temporary directory with the TEMP_DIR parameter set to /tmp/$session_id. This gave me a quasi-unique( yes, the possibility exists that there would be a collision ) directory that I could query the size of. When the user clicked the submit button I used a window.open( There's the javascript, I don't like its inclusion, but it works ) to pop-up a smallish window that would execute a subroutine to check the size of the directory /tmp/$session_id, and report in in MBs to the user. One thing that I wasn't able to do was actually create a progress bar. The hitch was that I had no prior knowledge of the file size before I was querying the size of the directory the file was being uploaded to. Apache::Request will report the size of the file uploaded, but only after the file has been uploaded. If you could somehow attain the filesize before the file is uploaded, you'd be able to knock out a quick GD script to show a progress bar. If you do figure out how to do that( short of user input ) please, let me know. I'd be most interested. My solution is, by no means elegant, but it works. And the requirment my boss gave me was that it worked. Elegance, sadly had to take a back seat.

    I hope this helps.
    Mac

    Everyone has their demons...you just happen to be mine.

      Mac

      This might be of interest to you as I have now managed to get the upload file name into a Perl script before the upload starts. I know javascript is the devil but I couldn't see any another way. Merlyn has a script using fork and CGI:FileCache which looks promising but I couldn't get it to run in a Win32 environment. Anyway, this is what I came up with:

      First the form:

      <form name="upload" action="filemngt_upload_file.pl" method="post" enc +type="multipart/form-data" onSubmit="showProgress()"> Enter the name of the file to uploaded: <input type="file" name="uploadfile" size="30"> <input type="submit" value="Upload File"> </form>

      As you can see from the above I have added the javascript event handle onSubmit which runs a javascript function called showProgress(). When the submit button is pushed the onSubmit event handler is processed before the main submit function. Here is the code for the showProgress() function:

      <SCRIPT LANGUAGE="JavaScript"> function showProgress() { var uploadfilename = document.upload.uploadfile.value; var newWindow = open("http://localhost/cgi-bin/test.pl?uploadfile=" + +uploadfilename, "secondWindow", "scrollbars,resizable,width=250,heigh +t=150,left=720"); } </script>

      Javascript allows you to access the name of the file for upload within a form. The line which begins with var = uploadfilename is where I'm setting a variable with the name of the file (which was entered by the user) for upload. I'm then opening a new window and calling a Perl script with the name of the file (to be uploaded) as a parameter.

      So I now have 2 Perl scripts running, one uploading the file and the other running (in another window) which knows the name of the file which is being uploaded so I can now add code to it to start monitoring the upload

      Hope this might be useful to you

      Eoin

      PS - All the above was tested (IE6) prior to this post

      Thanks Mac

      By the way, I am a multi-user demon as many monks will testify!

      Eoin