Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hello, I have found a perl script on the internet I wish to use for uploading files to a site, but I have been unsuccessfull in using it. I am very new to perl, so am not sure what's wrong with the code. Here's the perl code:
#!/usr/bin/perl -wT #use CGI; use CGI qw(warningsToBrowser fatalsToBrowser); #use CGI::Carp qw(warningsToBrowser fatalsToBrowser); $CGI::POST_MAX = 10000000; # Added as an example - limit POST to 10000 +k my $q = new CGI; # Create new query object my $filename = $q->param("pic"); my $upload_filehandle = $q->upload("pic"); # Corrected my $upload_dir="/pics"; $filename =~ s/.*[\/\\](.*)/$1/; print $q->header ("text/html" ); open UPLOADFILE, ">$upload_dir/$filename"; binmode UPLOADFILE; # to specify binary file operations on this fileha +ndle my $total_bytes = 0; while (my $bytes_read = read($upload_filehandle, $buffer, 1024)) { print UPLOADFILE $buffer; $total_bytes += $bytes_read; } close $upload_filehandle; close UPLOADFILE; print "<html>"; print "<head>"; print "<title>Thanks..!!!</title></head>"; # note closing head tag print "<body>"; print "<P>Thanks for uploading your photo!</P>"; print "<P>Your photo:</P>"; print "<img src=\"/pics/$filename\" border=\"0\">"; print "<p>Size of photo is $total_bytes bytes.</p>"; # Added line if d +esired. print "</body>"; print "</html>";
and here's the HTML code:
<FORM ACTION="http://192.168.1.50/cgi-bin/upload2.pl" METHOD="post" EN +CTYPE="multipart/form-data"> Photo to Upload: <INPUT TYPE="file" NAME="pic"> <br><br> <INPUT TYPE="submit" NAME="Submit" VALUE="Submit Form"> </FORM>
The html page works ok, put the picture isn't actually uploaded, so it just shows a broken picture icon. The apache error_log states: print() on closed filehandle main::UPLOADFILE at /Library/WebServer/CGI-Executables/upload2.pl line 23. and also that the .jpg file doesn't exist. I am testing it on my mac (OS 10.2) but but hope to put it up on my site at nic.nac.wdyn.de. Any help is much appreciated! From Edwin

Replies are listed 'Best First'.
Re: Picture upload script!
by jZed (Prior) on Sep 19, 2004 at 03:44 UTC
    open UPLOADFILE, ">$upload_dir/$filename";

    Always, yes always always, check the sucess of file open by adding

    or die "Couldn't open '$upload_dir/$filename': $!"

    update and print a content header before you print your thank you message, and make the top part look like this:

    use CGI; use CGI::Carp qw(fatalsToBrowser);

Re: Picture upload script!
by kesterkester (Hermit) on Sep 19, 2004 at 02:10 UTC
    Here's some code I used for a similar page I wrote once: the subroutine make_form makes the form the user fills out, and the upload_picture uploads the picture and writes it to the server's disk.

    The important snippets are:

  • $page->start_form ( -enctype => 'multipart/form-data' ) (necessary for the upload to work correctly)
  • $page->filefield ( 'picture' ) (creates the field for the user to input their imagename)
  • my $fh = $page->upload ( 'picture' ) or die "can't upload picture!"; (returns a filehandle to the user's image, which can now be used to write the image to the server)

    our @textfields = qw/Name Address City State Zipcode Phone Email/; sub make_form { my $page = shift () or die "no CGI object in make_form"; my $table = new HTML::Table ( -cols => 2 ); $table->addRow ( $page->strong ( 'Your Picture:' ), $page->filefield ( 'picture' ) ); $table->addRow ( $page->strong ( 'Order Type' ), $page->radio_group ( -name => 'order_type', -values => [ 'button', 'magnet' ], -rows => 1, -columns => 2, ) ); $table->addRow ( $page->strong ( $_ ), $page->textfield ( $_ ) ) foreach @textfields; my $form = $page->start_form ( -enctype => 'multipart/form-data' ) + . $table . $page->p . $page->submit ( 'place_order', 'Submit Order' ) . $page->end_form; return $form; } sub upload_picture { my $page = shift () or die "no page in upload_picture"; my $prefix = shift () or die "no prefix in upload_picture"; my $fh = $page->upload ( 'picture' ) or die "can't upload picture!"; my $img_fname = (split ( /\/|\\/, $page->param ( 'picture' ) ) )[- +1]; $img_fname = $prefix . "_" . $img_fname; open ( my $out_fh, '>', $img_fname ) or die "can't open output file in upload_picture: $!"; print $out_fh $_ while (<$fh>); close $out_fh or die "can't close output in upload_picture"; return $img_fname; }
Re: Picture upload script!
by Errto (Vicar) on Sep 19, 2004 at 03:51 UTC
    jZed is absolutely right, the error is most likely caused by your call to open not opening the file. I would go on to suggest that the likely reason for this is that "/pics" is not a top-level directory on your machine but is rather a sub-directory of your web root. So you should set your $upload_dir to a path (absolute or relative) to the actual directory where the file should go.
Re: Picture upload script!
by TedPride (Priest) on Sep 19, 2004 at 05:20 UTC
    The following is a bare bones upload script:

    WEB PAGE:

    <HTML> <TITLE>Upload File</TITLE> <BODY BGCOLOR="#FFFFFF"> <form method="post" action="/cgi-bin/upload.pl" enctype="multipart/for +m-data"> <input type="file" name="graphic" size="35"> <input type="submit" value=" Upload "> </form> </BODY> </HTML>
    PERL SCRIPT:
    #!/usr/local/bin/perl ############################################ $base = "/usr/home/web67378/www/htdocs"; $folder = "$base/upload"; use CGI; $query = new CGI; print "Content-Type: text/html\n\n"; if ($filename = $query->param('graphic')) { if ($filename =~ /^([\w-]+\.(jpg|gif|png))$/) { $file_handle = $filename; $filename = $1; open(OUT, ">$folder/$filename") || &error('The file could not be written to the server.'); while (read($file_handle,$buffer,1024)) { print OUT $buffer; } close($file_handle); close(OUT); } } else { &error('No file was selected for upload.'); } print "Successful."; sub error { print shift; exit; }
    Items of note:
    1) Edit $base and $folder as necessary.

    2) if ($filename =~ /^([\w-]+\.(jpg|gif|png))$/) {
    Edit this so it matches your desired file name pattern. The current pattern is for image files only.

    3. Add proper header and footer HTML so the output doesn't look like crud.