Uploading Files Using CGI and Perl
(2)
Step 2: Creating the File Upload CGI Script
Handling the data that the browser sends when it uploads a file is quite a complex process. Fortunately, the Perl CGI library, CGI.pm, does most of the dirty work for us!
Using two methods of the CGI query object, param() and upload(), we can retrieve the uploaded file's filename and file handle respectively. Using the file handle, we can read the contents of the file, and save it out to a new file in our file upload area on the server.
1. First Things First
The first things we need to do in our script are, of course, create the shebang line, and use the Perl CGI library:
#!/usr/bin/perl -w
use CGI;
Note the use of the -w to make Perl warn us of any potential dangers in our code. It's nearly always a good idea to put the -w in!
2. The Upload Directory
We need a location on our server where we can store the uploaded files. We want these files (photos) to be visible on our Website, so we should store them in a directory under our document root, for example:
$upload_dir = "/home/mywebsite/htdocs/upload";
So you'll need to create a directory called "upload" on your Website's document root, then set $upload_dir to the absolute path to that directory, as I've done above.
3. Reading the Form Variables
The next step is to read in the filename of our uploaded file, and the email address that the user entered into the form:
$query = new CGI;
$filename = $query->param("photo"); $email_address = $query->param("email_address");
Some browsers pass the whole path to the file, instead of just the filename, so it's a good idea to strip off everything that includes backslashes (Windows browsers) and forward slashes (Unix browsers) and which might appear before the filename:
$filename =~ s/.*[\/\\](.*)/$1/;
4. Getting the File Handle
As I mentioned above, we can use the upload() method to grab the file handle of the uploaded file (which actually points to a temporary file created by CGI.pm). We do this as follows:
$upload_filehandle = $query->upload("photo");
5. Saving the File
Now that we have a handle to our uploaded file, we can read its contents and save it out to a new file in our file upload area. We'll use the uploaded file's filename as the name of our new file:
open UPLOADFILE, ">$upload_dir/$filename";
binmode UPLOADFILE;
while ( <$upload_filehandle> ) { print UPLOADFILE; }
close UPLOADFILE;
The binmode function just after the open tells Perl to write the file in binary
mode, rather than in text mode. This prevents the uploaded file from being corrupted
on non-UNIX servers (such as Windows machines).
6. Thank the User
We've now uploaded our file! The last step is to display a quick thank-you note to the user, and to show them their uploaded photo and email address:
print $query->header ( );
print <<END_HTML;
<HTML>
<HEAD>
<TITLE>Thanks!</TITLE>
</HEAD>
<BODY>
<P>Thanks for uploading your photo!</P>
<P>Your email address: $email_address</P>
<P>Your photo:</P>
<img src="/upload/$filename" border="0">
</BODY>
</HTML>
END_HTML
The Finished Script
Your finished CGI script should look something like this:
#!/usr/bin/perl -w
use CGI; $upload_dir = "/home/mywebsite/htdocs/upload"; $query = new CGI; $filename = $query->param("photo"); open UPLOADFILE, ">$upload_dir/$filename"; while ( <$upload_filehandle> ) close UPLOADFILE; print $query->header ( ); <HTML> <BODY> <P>Thanks for uploading your photo!</P> </BODY> END_HTML |
Save this file on your hard drive, and call it "upload.cgi".
Now we've created our server-side script, we can place both the script and the form on our server and test the file upload.