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

Dear Monks,
i know this has been covered many times, but the code i have is just freaking me out. I tried to do it with as few as possible lines, but it would still give me silly errors, i just cant understand why?! here is the code, pls help if you can!
#!perl -wT use CGI; use CGI::Carp qw ( fatalsToBrowser ); use strict; use Fcntl qw ( :DEFAULT :flock ); use constant UPLOAD_DIR => "c:/some/path/Admin/images/"; my $q = new CGI; my $filename = $q->param('file'); my $fh = $q->upload('file'); $filename =~ s/[^\w.-]/_/g; if ($filename =~ /^(\w[\w.-]*)/) { $filename = $1; } else { error($q, "Invalid file name." ); } my $upload_dir = UPLOAD_DIR . $filename; sysopen(OUTPUT, $upload_dir, O_CREAT | O_RDWR | O_EXCL); my $buffer = ""; while (read($fh, $buffer, 16384)) { print OUTPUT $buffer; } close OUTPUT; print $q->header, $q->start_html("At long last"), $q->h1("done dude...doh"), $q->end_html;
As it is now, this would throw an error like:
Can't use an undefined value as a symbol reference at C:/some/path/aga +in.pl line 34.
or something like:
Error near ""binmode
Essentially i tried to follow the docs, made use of past posts here in <a href="www.perlmonks.org>perlmonks, with no apparent success though!!
Any help will do!!!
cheers
r_mehmed
novice

Replies are listed 'Best First'.
Re: file upload (again)
by tachyon (Chancellor) on Feb 08, 2003 at 11:38 UTC

    Your problem is probably an old version of CGI.pm which has a broken upload() method - some of them did from memory, that's part of the reason I wrote CGI::Simple. Anyway this can't be a cut and paste of your actual code as you show an error near ""binmode but you don't go no binmode in your posted code dude. The undefined filehandle can only be $fh. Change your code to this:

    $fh = $q->upload('file') or die_nice(); sub die_nice { print $q->header; print "<p>Failed again, lets look at our CGI.pm version: ", $CGI:: +VERSION print "<p>Now here is our CGI object"; use Data::Dumper; print '<pre>', $q->escapeHTML(Dumper $q), '</pre>'; exit; }

    I suspect that your HTML form does not specify either multipart/form-data or POST. Show us how you call the script from the HTML please. It MUST look pretty much like this or it is never going to work:

    <form method="post" action="http://mysite.com/cgi-bin/upload.cgi" enct +ype="multipart/form-data"> <p>Upload File <input type="file" name="file"> <br> <input type="submit" name="submit" value="Upload"> </form>

    Other points are that you get the constants from Fcntl but don't use them (probably won't work on Windows anyway). Your filename validation is also pretty pointless

    Did you follow my suggestions here?

    cheers

    tachyon

    s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

Re: file upload (again)
by poj (Abbot) on Feb 08, 2003 at 11:36 UTC
    You can only run this code from another form that provides the filename and handle, without them you get the error. I've added a simple form to your script to prove it works OK
    #!perl -wT use CGI qw(:standard); #### be sure to change this use CGI::Carp qw ( fatalsToBrowser ); use strict; use Fcntl qw ( :DEFAULT :flock ); use constant UPLOAD_DIR => "c:/upload/"; my $q = new CGI; my $filename = $q->param('file'); my $fh = $q->upload('file'); if ($fh){ #### check for filehandle $filename =~ s/[^\w.-]/_/g; if ($filename =~ /^(\w[\w.-]*)/) { $filename = $1; } else { error($q, "Invalid file name." ); } my $upload_dir = UPLOAD_DIR . $filename; sysopen(OUTPUT, $upload_dir, O_CREAT | O_RDWR | O_EXCL); my $buffer = ""; while (read($fh, $buffer, 16384)) { print OUTPUT $buffer; } close OUTPUT; print $q->header, $q->start_html("At long last"), $q->h1("done dude...doh"), #### add button to reset form $q->start_form( -action => url () ), $q->submit ( -name=>"done", -value=>"Done"), $q->end_form(); #### $q->end_html; #### simple form to choose file to upload } else { print $q->header, $q->start_html("Upload File"), $q->start_multipart_form( -action => url () ), "File : ", $q->filefield (-name=>"file", -size=>60), $q->submit ( -name=>"submit", -value=>"Submit"), $q->end_form(); $q->end_html; }
    poj
Re: file upload (again)
by zentara (Cardinal) on Feb 08, 2003 at 14:02 UTC
    If you want to do it in as few steps as possible, try this example using Tachyon's CGI::Simple.
    #!/usr/bin/perl use warnings; use strict; use CGI::Simple; my $maxsize = 1024 * 100; #max 100K my $upload_dir='uploads'; my $q = new CGI::Simple; print $q->header(); if($ENV{CONTENT_LENGTH} > $maxsize){ print "file too large - must be less than $maxsize bytes"; exit; } my $files = $q->upload(); # number of files uploaded +; my @files = $q->upload(); # names of all uploaded fil +es my $filename = $q->param('upload_file'); # filename of uploaded fil +e my $mime = $q->upload_info($filename,'mime'); # MIME type of uploa +ded file my $size = $q->upload_info($filename,'size'); # size of uploaded f +ile # short and sweet upload my $ok = $q->upload( $q->param('upload_file'),"$upload_dir/$filename") +; print "Uploaded ".$q->param('upload_file')." and wrote it OK!\n" if $o +k; print "total files = $files<br> filenames = @files<br> filename = $filename<br> mimetype= $mime<br> size=$size<br>";