If you need to create a tool to view the progress of a file upload from an HTML form to a Perl CGI script, there are a few things you’ll need to be aware of. I will explain the basic blueprint for what needs to be done to accomplish this task. One of the first challenges you might notice is that when you try to detect the progress from your CGI script, the file has already been uploaded by the time you can try to do anything. This is due to the way that the form data is fed to the CGI script. The key to this problem is to “capture” all the data that is being sent to the form. By the time you’ve declared your variable to hold your CGI data, the opportunity to view the progress of the file upload has already been lost. You need to capture the data being posted to the script before declaring your CGI variable.
######################################
#you need to detect the progress of the file upload before you declare your
#CGI variable
use CGI;
my $q = new CGI;
#at this point in your script, the data has already been transferred to the server
#and you cannot show the progress in real time
######################################
#!/usr/bin/perl
#keep track of how much data transferred so far
my $transferred_so_far = 0;
#set an interval for how often the upload progress will be updated
my $noticelimit = 10240; #this is 10KB, make larger to decrease reporting overhead
#capture the form data and write it to a unique file. This script has already safely determined
#a unique $username based on a login. Your script may have another way of handling this.
open TMP, "> ./$username.post" or die "cannot open file";
while (read (STDIN ,$LINE, 4096)) {
#this keeps track of how much has been uploaded so far
$transferred_so_far += length($LINE);
#we print the data to a unique user file, so we can re-read from a separate progress script
#while we are busy in this loop, another progress reporting script will read this file and
#report the data transfer in a separate pop-up window
print TMP "$LINE";
if ($currentnotice > $noticelimit) {
#at every interval of $noticelimit, we will write the upload status to a unique file
open NOTICE, "> ./$username.notice" or die "cannot open file";
print NOTICE "$tmpsofar Bytes transferred so far..";
close(NOTICE);
$currentnotice = 0;
}
}
close(TMP);
#now that the data transfer is complete, go ahead and declare your CGI variable and read in
#the captured data from your temp file to standard in
open(STDIN,"$username.post") or die "can't open temp file";
my $q = new CGI;
Now you are in a position where you can create a separate script that will simply read the contents of the $username.notice file and report what it finds. You can set this script to refresh itself every few seconds and that will serve to show the progress of the data transfer. Placing this script in a small popup window that you can launch when the submit button is clicked for the file upload will handle this nicely.