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

I'm trying to add a file upload feature to some perl code and there seem to be a lot of very different examples on the web, most of them either different from my approach or just way over my head. My HTML code and pages are very basic and provide simple but sufficient functionality. Here is a fragment of my code that should be enough to show what I am trying to do:
#!/usr/bin/perl -w # code_fragment.pl use strict; use CGI qw(:standard escapeHTML); # ------ start posting to browser ------ print header (), start_html( (-head => [ Link ({ -rel => 'icon', -type => 'image/png', -href => '/perl_img/my_icon_01.ico'}) +, ] ), (-title => "My File Upload Utility", -bgcolor => "whit +e") ); print ('<IMG SRC="http://' . $server_ip_addr . '/image004.jpg" /><br / +>' . "\n"); print ('<h2>UPLOAD A NEW FILE</h2>' . "\n"); # ------ post form to browser ------ print start_multipart_form(-action => url()), '<input type="hidden" name="MAX_FILE_SIZE" value="5000" />', "\n", 'Select file to upload: ', "\n", '<input name="uploadedfile" type="file" size="40"/><br />', "\n", "<br /><br />\n", "<br /><br />\n", '<input type="submit" name="choice" value="Upload File" />&nbsp;&nb +sp;&nbsp;', "\n", '<input type="submit" name="choice" value="Abort Upload" />', "\n", end_form(); print end_html(); exit(0);
My code puts a working file upload box on the browser and seems to work properly. After the browser returns I have the file name in param("uploadedfile") as expected. My problem is I don't know how to access the file.

Some of the php file-upload examples on the web seem very easy. Apparently in php $_FILES['uploadedfile']['name'] will contain the path and name of the file on the client machine and $_FILES['uploadedfile']['tmp_name'] will contain the path and name of the temporary file that the browser uploaded onto the server after the input type=file executed. Use this to copy the file to the final location and a useful file upload is done.

It would be great if someone could look at my code and let me know if something as simple as the php example can be done in perl. Everything I find goes off into advanced CGI and Apache calls and leaves me feeling like I could spend days and many failures just to do something simple.

Thanks,
Bruce

Replies are listed 'Best First'.
Re: File upload under Apache2
by Anonymous Monk on Aug 16, 2010 at 03:27 UTC
    Everything? perldoc CGI

    http://search.cpan.org/~lds/CGI.pm-3.49/lib/CGI.pm#PROCESSING_A_FILE_UPLOAD_FIELD

    $lightweight_fh = $q->upload('field_name'); # undef may be returned if it's not a valid file handle if (defined $lightweight_fh) { # Upgrade the handle to one compatible with IO::Handle: my $io_handle = $lightweight_fh->handle; open (OUTFILE,'>>','/usr/local/web/users/feedback'); while ($bytesread = $io_handle->read($buffer,1024)) { print OUTFILE $buffer; } }
    or
    $filename = $query->param('uploaded_file'); $tmpfilename = $query->tmpFileName($filename);
      Thank you for the reply.

      I have spent about 20 minutes trying to get it to work. Initially I did not have anything similar to $q = CGI ->new; in my code. Adding that and your suggestion initially caused server errors to be posted on the browser. After debugging several minor mistakes and/or cut and paste issues on my part I now have no server errors, but it still does not seem to work.

      I'll keep plugging away at it, but any other suggestions would be appreciated. Having to add $q = CGI ->new; and dealing with lightweight and regular file handles is stretching my perl knowledge. Up until the file upload, the various submit buttons, text fields, radio buttons, etc. were all working well without them.

      Thanks,
      Bruce
Re: File upload under Apache2
by CountZero (Bishop) on Aug 16, 2010 at 08:53 UTC
    Don't make it more difficult than necessary: CGI::Simple has a file upload() method. Have a look at the FILE UPLOADS section of the documentation.

    Update: Or even easier: CGI::UploadEasy or CGI::Upload.

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

      CGI::Simple uses the exact same interface as CGI, and CGI::UploadEasy and CGI::Upload aren't any easier to use
        Beauty or (ease of use) is in the eye of the beholder and sometimes things need to be repeated before they sink in.

        CountZero

        A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

        Minor quibble. It's not "the exact same interface".

        From the docs:

        By utilizing a new feature of the upload method this process can be si +mplified to: $ok = $q->upload( $q->param('upload_file1'), '/path/to/write/file. +name' ); if ($ok) { print "Uploaded and wrote file OK!"; } else { print $q->cgi_error(); } As you can see upload will accept an optional second argument and will + write the file to this file path. It will return 1 for success and u +ndef if it fails. If it fails you can get the error from cgi_error.
        imo, a nice improvement.
Re: File upload under Apache2
by Bruce32903 (Scribe) on Aug 16, 2010 at 15:05 UTC
    Thank you for all the responses so far. I'm tied up for a few hours and will probably not get back to it until tonight.

    I don't want to ruffle any feathers more than I already have but in Perl there is a pretty big jump going from beginner to intermediate skill levels. All the various ways of doing things, different methods, different packages, etc. can be overwhelming to someone who doesn't yet have the intermediate/advanced insight into the inner workings of Perl. It is easy to look at a variety of books and postings and feel like they all go in different directions and are inconsistent with each other. In some cases this is true, in some cases it isn't. But we beginners can look at the various methods and various shortcuts and end up going around and around in pointless circles until we are too burned out to see what is in front of our face. I think of myself as a Perl advanced beginner. I have been around Perl for years, but only writing a couple of small programs a year I have never made that jump up to having better insight into the inner workings of Perl.

    I try not to post code unless it is as clean, short and to the point as possible. If I am going to ask someone to take their time to look at my code I try not to waste their time. I also know that once I have posted some garbage code to the thread I have probably killed the possibility of people taking the time to read any code that might follow it. I ran out of time last night and didn't have another batch of clean code to post.

    One of the great things about Perl is that there are many ways to do things and many shortcuts available to make coding easier for those with knowledge and skill. One of the bad things about Perl is that there are many ways to do things and many shortcuts that make understanding difficult for those with limited Perl knowledge and skill.

    Beginners can struggle for a long time with two different tutorials that have details that look very different (to the beginner). There are times when after hours of work and Googling a beginner finds out that something from one source is only good for Perl X.X and below where something from another source is only good for Perl Z.Z and above. We can spend hours only to find out that it was common knowledge within the Monk community that we were barking up the wrong tree.

    The questions from us beginners reflect that we do not yet have the knowledge and insight of intermediate/advanced Monks. Some days no matter how many times Grasshopper grabs for the pebble we still come up empty handed.