Perlfect Solutions
 

Handling file uploading from www forms with CGI.pm

Introduction

Netscape Navigator 2.0 introduced a new facility for forms, the file upload element. This element allows the user to select a local file to be submitted with the form to the server that handles the form. File uploading is a frequently needed facility in many occasions, but the technique involved in handling forms that upload files is rarely discussed in CGI programming texts, and online tutorials/references on this topic are few. The technique is very simple as we shall see.

The form

First of all we'll need to prepare the HTML form that will contain the file upload element:
<FORM ENCTYPE="multipart/form-data" ACTION="/cgi-bin/upload.pl" METHOD="POST"> Please choose directory to upload to:<br> <SELECT NAME="dir"> <OPTION VALUE="images">images</OPTION> <OPTION VALUE="sounds">sounds</OPTION> </SELECT> <p> Please select a file to upload: <BR> <INPUT TYPE="FILE" NAME="file"> <p> <INPUT TYPE="submit"> </FORM>

Which will look on the browser like that:
Please choose directory to upload to:

Please select a file to upload:

Notice the form parameter ENCTYPE="multipart/form-data" which determines the encoding that will be used to submit it.

The CGI script

On the server side, we'll have the CGI program (upload.pl) that will handle the upload. We will use CGI.pm that does all the dirty job for us. CGI.pm processes the submission of the form for us and provides us with a simple method of retrieving each individual part of the submission. In our case we only have one element, called file:

1 #!/usr/bin/perl 2 use CGI; 3 my $cgi = new CGI; 4 my $dir = $cgi->param('dir'); 5 my $file = $cgi->param('file');

Now it is quite obvious what the value of $dir will be. But what will the value of $file be assigned to? ACtually $file now is two things:
  1. In a scalar context it is the filename on the client computer, as it appears in the file selection box.
  2. When used in a filhandle context, it behaves as a read-mode filhandle from which the uploaded file can be read just like any normal file opened locally. (actually what happens here is that CGI.pm keeps the upload in a temporary file and provides us with an open handle to it so we can read through it)
And that's all there is to it. Now all we got to do is read in the file and store it somewhere or do whatever else we might want to do with it.

6 $file=~m/^.*(\\|\/)(.*)/; # strip the remote path and keep the filename 7 my $name = $2; 8 open(LOCAL, ">$dir/$name") or die $!; 9 while(<$file>) { 10 print LOCAL $_; 11 } 12 print $cgi->header(); 13 print "$file has been successfully uploaded... thank you.\n"; First of all, because the filename that we get from the form includes the full path of the file on the remote machine we need to strip that part. Lines 6-7 do just that. Next we open a local file and we just iterate through the upload input and dump its contents to it. Finally we print out a message back to the browser to confirm that the upload has been successful.

Online Documentation/Tutorials

  • The POD documentation for CGI.pm has a section explaining all you need to know about file uploading.

Digg! Save This Page

Comments

perlfect   

Posted at 7:51pm on Friday, June 8th, 2007

6 $file=~m/^.*(\|/)(.*)/; # strip the remote path and keep the filename
7 my $name = $2;
8 open(LOCAL, ">$dir/$name") or die $!;
9 while() {
10 print LOCAL $_;
11 }
12 print $cgi->header();
13 print "$file has been successfully uploaded... thank you.n";

June 8th, 2007   

Posted at 7:54pm on Friday, June 8th, 2007

perl with explanations and tips easy to understand even for beginners, but also frequently useful even to more experienced programmers. The code is clear and straightforward and the topics covered as well-thought and correspond to real world examples, so frequently you can literally copy code snippets from the book and fit them in your program

error 500   

Posted at 6:54am on Thursday, June 14th, 2007

HI
I am getting this error in the browser what might be the problem "HTTP Error 500 - Server Error" Please help to find the error .Regards Shashi

security check   

Posted at 3:59pm on Monday, June 18th, 2007

I see this is meant to be simple example, but many people will just copy and paste this dangerous snippet into their CGI script. If you don't want to be pwned, you must overcome laziness and:
1. strip any dangerous characters from directory parameter, or check directory name against predefined list on server.
2. ensure uploaded files can't be executed.
Afterabove is done, running with perl -T is encouraged.

Jeff   

Posted at 3:15am on Thursday, July 26th, 2007

Please stop posting terrible perl scripts that will cause those who use them security problems. Please!

Taureth   

Posted at 8:48pm on Tuesday, August 28th, 2007

The VERY simple example is appreciated... I needed info on file upload, not a course in security issues, so it was perfect for me... those who are too lazy or stupid to include security coding probably deserve to get what they asked for...

Cherry   

Posted at 11:24pm on Wednesday, August 29th, 2007

When executed..
# perl upload.pl
# err msg :Is a directory at upload.pl line 8.
Consequently 500 Internal Serv Err !!

Wat Could Be Done??

DT   

Posted at 5:37pm on Sunday, November 18th, 2007

RE:Cherry

You need to:
a) create the directory
b) allow write access to the directory(DO NOT ALLOW 777!)

samirzedan   

Posted at 8:24am on Friday, January 11th, 2008

On the excellent site and wish to participate in it

Gregory Swofford   

Posted at 3:35am on Monday, January 14th, 2008

Here's a snippet I include anytime I use CGI.pm. You can trap all your errors to debug a script. If the file 'error.log' doesn't exist, the server will create it as 'user nobody'.

# FOR DEBUGGING:
#use strict;
use CGI qw(:standard);
use CGI::Carp qw(fatalsToBrowser);
BEGIN {
open (STDERR, '>>error.log');
}
# END FOR DEBUGGING

Neil Fraser   

Posted at 12:57pm on Monday, March 3rd, 2008

Don't forget to CLOSE the file while you are done. Your operating system has a limited number of file handles.
close(LOCAL);

axe   

Posted at 3:56pm on Thursday, March 27th, 2008

my file uploads but it does not have any data. Any suggetion ?

Tim   

Posted at 4:06pm on Monday, May 26th, 2008

an empty file sometimes means the form HTML didn't include ENCTYPE="multipart/form-data" I have been stung with this a few times and it drove me crazy until I figured it out :) Also a note for beginners, $dir needs to be something otherwise it may try and put your file in the wong place, ie:
my $dir="pics"; # and make sure the directory pics is in the same directory as the script is being run from.

James   

Posted at 12:40pm on Tuesday, July 8th, 2008

Didn't work for me. Where do you create the directory? Do you have to put absolute path (like /var/www/html/sounds). Please help.
Thx.

JD   

Posted at 7:17am on Wednesday, August 13th, 2008

Hi I have a question
is it possible to delay the actual data file upload until the $cgi->param('file') or $cgi->upload('file') are called ?
this is because I would like to include some validation before the server really transfers the data and use the bandwidth ....

Anonymous   

Posted at 10:46pm on Wednesday, August 13th, 2008

In my case both server and client are on same machine.
When i click for upload file , upload.pl is opened!

Indraraj Chakrabarty   

Posted at 12:11pm on Sunday, September 21st, 2008

sub uploadFile()
{
$file = $pic;
$file=~m/^.*(\|/)(.*)/; # strip the remote path and keep the filename
my $name = $2;
open(LOCAL, ">$name") or die $!;
binmode LOCAL; ****
while() { print LOCAL $_; }
#print $cgi->header();
print "$file has been successfully uploaded... thank you.n";
}

*** --> "you should add this line as well which ensures that the file is uploaded in the binmode. this will make it useful for both Windows or Unix. Or else you may find the picture is not opening and showing type not recognized"

Comments to date: 17.

Your name:
Your comments:

Security check *

 

Like it? Share it!

  Post to del.icio.us
Post to
del.icio.us
   

Suggested Reading

Official CGI.pm Programming Guide The Official CGI.pm Programming Guide is the definitive manual and guidebook for writing CGI programs with perl and the CGI library. While the manual distributed with the library as part of perl's documentation is well written and covers almost anything you'd need to know about using CGI.pm, this book is a useful companion for anyone making CGI scripts with perl.
CGI Programming CGI Programming is an introductry book for CGI programming, perhaps not the best book I've read. It covers most topics about the CGI protocol and how to write server side programs to work with it. Nevertheless, most if not all of the information in this book (as with most books that discuss CGI programming) can be found in tutorials and references on the web, but if you feel like buying a book anyway, you may want to consider this one.
Webmaster In A Nutshell Webmaster in a nutshell is a catch-all reference book for webmaster and programmers. It does not have anuything that you can't find online, but if you're liek me you might want to have all the stuff you refer to frequently nicely laid out in a well-organized book lying on your desk. If you're looking for something like that then you'll be happy with this book.
Perl Cookbook The Perl Cookbook is full of quick solutions to everyday programming problems in perl with explanations and tips easy to understand even for beginners, but also frequently useful even to more experienced programmers. The code is clear and straightforward and the topics covered as well-thought and correspond to real world examples, so frequently you can literally copy code snippets from the book and fit them in your program. It is a nice complement for the Camel Book on your bookshelf.