The following is a simple example of using the popular CGI.pm module written by Lincoln Stein to upload files. This FAQ is not an exhaustive treatment of the topic. Instead, it is a FAQ ;^). Also, be aware that any time you let anyone put files on your machine you are taking a chance....Be paranoid. For more information on CGI.pm, see it's documentation. To find out how to do that, see the FAQ, "How can I use Perl's built-in help".
This is presented as two files. It could as easily be one CGI file that does the entire trick. It is presented as two files for clarity. The first is a very simple HTML page with the necessary parts to allow the upload to run. The second is a piece of CGI code which accepts the input from the HTML page and reads the file from the client. Absolutely no attention has been paid to aesthetics.
**** HTML Page *****
<HTML>
<HEAD>
<TITLE>UPLOAD THIS</TITLE>
</HEAD>
<BODY>
<!-- change the next line to point at your cgi code. -->
<FORM METHOD="POST" ACTION="http://some.server.com/cgi-bin/upload.cgi" ENCTYPE="multipart/form-data">
<P>Enter or Browse to the file you would like to upload.<BR>
<INPUT TYPE="file" NAME="FILEID" VALUE="" SIZE=50 MAXLENGTH=80><BR>
<INPUT TYPE="submit" NAME="submit" VALUE="uploadMe"></FORM>
</BODY>
</HTML>
**** End HTML Page ****
Note that the <FORM.... ACTION=.....>, above, must be editted to point to
where you put the CGI code. Note, also, in the first <INPUT ...> tag above the
NAME is 'FILEID'. That will be important in the CGI code. The CGI code below
would be written into a file named like the <FORM ....ACTION=....> and,
if you are on a UNIX box, set the execute bits to the web server daemon can run it.
Also, if you are on a UNIX box, don't forget to convert dos2unix if you got this stuff via a PC.
**** Start CGI ****
#!/usr/local/bin/perl
use CGI;
$query = new CGI;
print $query->header;
print $query->start_html(-title=>"UPLOAD PLEASE");
# retrieve the upload file name. Note that it is retrieved with
# the same name here ('FILEID') that it has in the HTML.
unless ($fileID = $query->param('FILEID'))
{ &showError('No file name specified.'); }
# Check to make sure the uploaded file is safe to keep
# by checking its type.
# First retrieve the file type .
# If it is not 'text/html' or 'text/plain', stop and complain.
# You can modify the regex to allow the types you would
# like to accept. If you don't know how, see the FAQ on
# pattern matching.
# I recommend against excluding types. Instead, you should
# explicitly define the types you want to accept.
$type = $query->uploadInfo($fileID)->{'Content-Type'};
unless ($type =~ /text\/[html|plain]/i)
{
&showError("Dangerous file type of $type.<BR>UPLOAD ABORTED.");
}
# If we are still running (did not bail on the file type and fileID exists),
# then,
@pathName = split(/\\/,$fileID);
# Read file from remote machine and write locally.
# You must change the following line to point to a
# dir on your machine that is writable by the web server daemon
$newFile ='/path/to/put/the/new/file/';
# add the upload filename to the new path
$newFile .= pop(@pathName);
# open a handle to the new file you will write
open(OPF,">$newFile") || &showError("Failed to open OPF, $!");
# while you read from the remote machine,
# write to the output file.
print "<P><CENTER>Uploading <BR>$fileID <BR>to<BR>$newFile<BR></CENTER></P>\n";
while ($bytesread=read($fileID,$buffer,1024))
{
print OPF "$buffer";
# The 1024 buffer size is nearly arbitrary.
# Watch to make sure the file is not to large.
# Someone could fill your file system if this is
# not watched. The 27000 byte limit is also arbitrary.
# You need to set it to an appropriate number for
# your situation.
# The $bytesread value comes into the while loop
# in 1024 $buffer chunks, so add up the chunks as they come.
$sum_bytes += $bytesread;
if ($sum_bytes > 27000)
{
close OPF;
unlink $newFile;
&showError("File is to large.");
}
}
close OPF;
print $query->end_html;
sub showError
{
# a generic complaint generator
my @error = @_;
print "<CENTER><font color=\"\#ff4500\">ERROR - @error</font><BR>\n";
print "Please use the BACK button to return to the previous page<BR>\n";
print "and correct the error.<BR></CENTER>\n";
print $query->end_html;
exit;
}
**** End CGI Code ****
'hope this is useful.