?
Solved

multiple file upload trouble

Posted on 2000-02-13
4
Medium Priority
?
167 Views
Last Modified: 2010-03-05
Could somebody tell me why the following script will not upload more than one file? What do I need to change or add to get it to at least upload 5 files at a time?

NOTE: $FULLPATH just refers to a valid path on my server
#######----BEGIN SCRIPT -----#########

# Define upload directory
$dir = "${FULLPATH}cgi_user_dir";

# Set maximum size of upload directory in kilobytes
$quota = 3072;

# Start main program

$content_type = $ENV{'CONTENT_TYPE'};
$content_len = $ENV{'CONTENT_LENGTH'};
$request_method = $ENV{'REQUEST_METHOD'};

&CheckRequest;
&ParseForm;
&Verify;
&Dir;
&SaveFile;
&Confirm;
exit;

# End main program

# Subroutines

sub ParseForm
# This piece of code is obtained from Tod Sambar for reading multipart
# form data. See http://www.sambar.com
 { # Begin ParseForm

      # Buffer the POST content
      binmode STDIN;
      read(STDIN, $buffer, $content_len);

        # find boundary
        # Eric Poulsen fixed the following to allow for quotes.
        # ($boundary = $content_type) =~ s/^.*boundary=(.*)$/\1/;
        ($boundary = $content_type) =~ s/^.*boundary="?(.*?)"?$/$1/;
          @pairs = split(/--$boundary/, $buffer);
          @pairs = splice(@pairs,1,$#pairs-1);
          for $part (@pairs)
           {
            ($dump,$fline,$value) = split(/\r\n/,$part,3);
            next if $fline =~ /filename=\"\"/;
            $fline =~ s/^Content-Disposition: form-data; //;
            (@columns) = split(/;\s+/, $fline);
            ($name = $columns[0]) =~ s/^name="([^"]+)"$/$1/g;
            if ($#columns > 0)
             {
              if ($value =~ /^Content-Type:/)
               {
                ($dump,$dump,$value) = split(/\r\n/,$value,3);
               }
              else
               {
                ($dump,$value) = split(/\r\n/,$value,2);
               }
             }
            else
             {
              ($dump,$value) = split(/\r\n/,$value,2);
              if (grep(/^$name$/, keys(%CGI)))
               {
                if (@{$FORM{$name}} > 0)
                 {
                  push(@{$FORM{$name}}, $value);
                 }
                else
                 {
                  $arrvalue = $FORM{$name};
                  undef $FORM{$name};
                  $FORM{$name}[0] = $arrvalue;
                  push(@{$FORM{$name}}, $value);
                 }
               }
              else
               {
                next if $value =~ /^\s*$/;
                $FORM{$name} = $value;
               }
              next;
             }
            $FORM{$name} = $value;
           }
 } # End ParseForm
      
sub SaveFile
 { # Begin SaveFile

      $filename = "$dir/$upname";
      open(FILE, ">$filename") || &error("Cannot open file $filename for writing: $!");
      binmode FILE;

      print FILE $upfile;
      close FILE;

 } # End SaveFile

sub CheckRequest
 { # Start CheckForm

   if ($request_method ne "POST")
    {
     &error("Request method should be \"POST\".");
    }

   if ($content_type !~ m#^multipart/form-data#)
    {
     &error("Content-type should be multipart/form-data");
    }

 } # End CheckRequest

sub Confirm
 { # Start Confirm
   print <<"(END CONFIRM HTML)";
Content-type: text/html

<HTML>
 <HEAD>
  <TITLE>Confirm upload</TITLE>
 </HEAD>
<BODY BGCOLOR=\"#8080ff\" TEXT=\"#000000\" LINK=\"#ffff00" VLINK=\"#800000\">
<P>
You're file has been uploaded!
<P>
<A HREF=\"/~falanx/\">Home</A>
</BODY>
</HTML>
(END CONFIRM HTML)
 } # End Confirm

sub error
 { # Start error
  $Error = $_[0];
  print <<"(END ERROR HTML)";
Content-type: text/html

<HTML>
 <HEAD>
  <TITLE>Error</TITLE>
 </HEAD>
<BODY BGCOLOR=\"#8080ff\" TEXT=\"#000000\" LINK=\"#ffff00\" VLINK=\"#800000\">
<CENTER>
 <H1>Error</H1>
</CENTER>
<P>
$Error
<P>
Please click on the Back button to return.
</BODY>
</HTML>
(END ERROR HTML)
exit;    
 } # End error

sub Dir
 { # Start Dir

@sizes=(); # Define empty list with sizes of files in upload dir
opendir (DIR, $dir) || &error("Unable to open directory $dir: $!");
 while ($file = readdir (DIR))
  {
   if ($file eq ".")
   {
    # Do nothing!
   }
   elsif ($file eq "..")
   {
   # Do nothing!
   }
   else
   {
   $size = -s "$dir/$file";
   push (@sizes, $size);
   }
  }

 $totalsize = 0;
 foreach $singlesize (@sizes)
  {
   $totalsize = $totalsize + $singlesize;
  }

 $newsize = ($totalsize + $content_len)/1024; # Size in kilobytes
 if ($newsize > $quota)
  {
   &error("Maximum directory size reached... Sorry");
  }

closedir (DIR);
 } # End Dir

sub Verify
 { # Start Verify

  $upfile = $FORM{'upfile'};
  ##@upload_string = split(/:/,$upfile);
 
  $upname = $FORM{'upname'};
  $upname =~ s/[\n\r\s\0]//g;
  $filename = "$dir/$upname";

  $filesize = -s $filename;
  if (!($upfile) || !($upname))
   {
    &error("No upload file specified!");
   }

  if ($upname =~ /[;><&\*'\|\/\\]/ )
   {
    &error("The upload file name is invalid.");
   }

  if ($filesize)
   {
    &error("File $upname does already exist");
   }

 } # End Verify


#####-----END SCRIPT ------ ########

0
Comment
Question by:microboard
  • 2
  • 2
4 Comments
 
LVL 16

Expert Comment

by:maneshr
ID: 2519343
try this. Using this approach you can upload as many files as you want.
Also the code size is reduced by a lot.

NOTE: right now the output goes to a single file and the total size/quota is 30000 bytes. Also i have added a hidden var just to show that other varibles can be used too.

==============multi_upload.html
<form ENCTYPE="multipart/form-data" action="/cgi-bin/multi_upload.pl" Method=POST>
Attach:<input name="upfile" type="file"><br>
Attach:<input name="upfile" type="file"><P>
<input type=hidden name="test" value="yes">
<INPUT TYPE=SUBMIT>
</form>


===============multi_upload.pl
#!/usr/local/bin/perl

use CGI;

$query=new CGI();
@upfile=$query->param('upfile');
$test=$query->param('test');
$quota=30000;

$dir = "/tmp/";
print "Content-type: text/html\n\n";

  $filename=$dir."test.txt";
  open(OUT,">$filename") || die $!;
  binmode OUT;

foreach(@upfile){
  chomp($filename);

  print "Reading $_<BR>\n";
  while($bytesread=read($_,$data,1024)){
    $size+=$bytesread;
    if ($size<$quota){
      print OUT $data;
    }else{
      close (OUT);
      print "Quota Exceeded<br>\n";
      exit;
    }
  }

  print "<hr size=4><br>\n";
}

close(OUT);
print "<B>Read $size bytes</B>\n";
print "<B>Testing var is $test</B>\n";

0
 

Author Comment

by:microboard
ID: 2520474
maneshr, thanks. Make it an answer now so I can give you the points.
0
 
LVL 16

Accepted Solution

by:
maneshr earned 400 total points
ID: 2520505
try this. Using this approach you can upload as many files as you want.
                   Also the code size is reduced by a lot.

                   NOTE: right now the output goes to a single file and the total size/quota is 30000 bytes. Also i
                   have added a hidden var just to show that other varibles can be used too.

                   ==============multi_upload.html
                   <form ENCTYPE="multipart/form-data" action="/cgi-bin/multi_upload.pl" Method=POST>
                   Attach:<input name="upfile" type="file"><br>
                   Attach:<input name="upfile" type="file"><P>
                   <input type=hidden name="test" value="yes">
                   <INPUT TYPE=SUBMIT>
                   </form>


                   ===============multi_upload.pl
                   #!/usr/local/bin/perl

                   use CGI;

                   $query=new CGI();
                   @upfile=$query->param('upfile');
                   $test=$query->param('test');
                   $quota=30000;

                   $dir = "/tmp/";
                   print "Content-type: text/html\n\n";

                     $filename=$dir."test.txt";
                     open(OUT,">$filename") || die $!;
                     binmode OUT;

                   foreach(@upfile){
                     chomp($filename);

                     print "Reading $_<BR>\n";
                     while($bytesread=read($_,$data,1024)){
                       $size+=$bytesread;
                       if ($size<$quota){
                         print OUT $data;
                       }else{
                         close (OUT);
                         print "Quota Exceeded<br>\n";
                         exit;
                       }
                     }

                     print "<hr size=4><br>\n";
                   }

                   close(OUT);
                   print "<B>Read $size bytes</B>\n";
                   print "<B>Testing var is $test</B>\n";
0
 

Author Comment

by:microboard
ID: 2521538
thanks
0

Featured Post

2018 Annual Membership Survey

Here at Experts Exchange, we strive to give members the best experience. Help us improve the site by taking this survey today! (Bonus: Be entered to win a great tech prize for participating!)

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

A year or so back I was asked to have a play with MongoDB; within half an hour I had downloaded (http://www.mongodb.org/downloads),  installed and started the daemon, and had a console window open. After an hour or two of playing at the command …
Article by: Tammy
MySQLTuner is a script written in Perl that allows you to review a MySQL installation quickly and make adjustments to increase performance and stability. The current configuration variables and status data is retrieved and presented in a brief forma…
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
Six Sigma Control Plans
Suggested Courses

601 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question