http://qs1969.pair.com?node_id=700594

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

I have the following code to upload a file to a webserver:
#!/usr/bin/perl -w use CGI qw (:standard); use CGI::Carp qw( fatalsToBrowser ); $CGI::DISABLE_UPLOADS=0; print header; $fh = upload('photo'); print h1("$fh"); open(PIC,'>>../pic.jpg') || die "Cannot open file: $!"; binmode(PIC) || die "Cannot binmode: $!"; while (<$fh>) { print $_; } close(PIC); print br,Dump,br; print br, img{src=>"../pic.jpg"};
Now I know it won't actually print to the file as it is, I changed the print statement so it should print straight to the browser. However, all it returns is
<h1>E:\309856393_0b02b023d6.jpg</h1><br /><ul> <li><strong>photo</strong></li> <ul> <li>E:\309856393_0b02b023d6.jpg</li> </ul> <li><strong>submit</strong></li> <ul> <li>GO FOR IT</li> </ul> </ul><br /><br /><img src="../pic.jpg" />
in IE and
<h1>309856393_0b02b023d6.jpg</h1><br /><ul> <li><strong>photo</strong></li> <ul> <li>309856393_0b02b023d6.jpg</li> </ul> <li><strong>submit</strong></li> <ul> <li>GO FOR IT</li> </ul> </ul><br /><br /><img src="../pic.jpg" />
in Firefox. It does this whether I do <$fh> or read($fh,$buffer,1024). Is there something I'm missing or do I need to do something else to make it read the file?

Replies are listed 'Best First'.
Re: CGI Form File Upload Read Problem
by moritz (Cardinal) on Jul 28, 2008 at 17:17 UTC
    open(PIC,'>>../pic.jpg')

    Are you sure that your upload script should attempt to append to that file?

    Did you verify that the file you're trying to upload actually contains what you think it does?

Re: CGI Form File Upload Read Problem
by themage (Friar) on Jul 28, 2008 at 17:28 UTC
    Hi zuluwarhelmet, My most frequent problem with upload forms is that I forget to change the enctype of the form. Aren't you making the same mistake? I'm talking about the enctype parameter on the form tag:
    <form enctype="multipart/form-data" method="POST"> <input type="file" name="upload"/> </form>
Re: CGI Form File Upload Read Problem
by olus (Curate) on Jul 28, 2008 at 17:38 UTC

    When you want to send an image from a Perl script straight to browser, you'll have to send the proper content-type header and then the contents of the file. Aside from that, your problem may be permissions. Are you sure you can write to ../?

      I've written to a text file. It seems to just not read from the file that's supposed to be uploaded.
Re: CGI Form File Upload Read Problem
by zuluwarhelmet (Novice) on Jul 28, 2008 at 17:42 UTC
    Sorry, I should've given the form HTML as well.
    <html><body><h3>hi!</h3><br><br> <form enctype="multipart/form-data" method="POST" action="./cgi-bin/up +load.pl"> Upload a picture: <input type="file" name="photo"><br> <input type="submit" name="submit" value="GO FOR IT"> </form> </body></html>
    I changed >> to > so it's not just appending, but that wouldn't have mattered since that file was made when I used > the first time.
Re: CGI Form File Upload Read Problem
by zuluwarhelmet (Novice) on Jul 29, 2008 at 02:36 UTC
    I think it may be the servers I'm using... I'm not sure. I don't understand IIS enough to set it up correctly I guess, and I've tried it on two remote servers and I get the same answer for either input method: Cannot read file: Bad file descriptor

    I also tried accomplishing this task using PHP on each of the remote servers and still neither received the file on either Firefox or IE. I don't quite understand what's going on. Thanks for trying to help though.
Re: CGI Form File Upload Read Problem
by olus (Curate) on Jul 29, 2008 at 10:01 UTC

    Maybe you should be working on the methods through an instance of CGI. This works for me: (with some more code in the midle, but this is the relevant part)

    use CGI; my $q = CGI->new; my $fileHandle = $q->upload('file'); my $file = $q->param('file'); my ($buffer, $bytesread); my $newfile = "/path/to/file"; open FILE, ">$newfile"; while($bytesread = read($fileHandle, $buffer, 1024)) { print FILE $buffer; } close FILE;

      Sorry, I misread the code. Please ignore this post (or reap it, if you feel like).

      Whoa there, don't ever dare to recommend that again.

      Letting a user of a CGI script specify an arbitrary file name, and use that file to name write without any checks (and in the two argument form of open, to make things worse) is one of the scariest things you can do when writing CGI scripts.

      Even when you do some verification on the file name it's notoriously hard to get it right. I'd recommend to generate file names in your script, perhaps with File::Temp.