Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery

Getting a filehandle for uploaded file

by luker (Initiate)
on Oct 20, 2009 at 12:44 UTC ( #802217=perlquestion: print w/replies, xml ) Need Help??
luker has asked for the wisdom of the Perl Monks concerning the following question:

On an old Redhat system with perl 5.6, this was part of the code to read an uploaded file and write to a file in the file system:

while (read($fh, $buffer, 1024)) { print $out_handle $buffer; }

where $fh was simply the name of the uploaded file. I am migrating the code to a Debian box with perl v5.10.0 and the above has stopped working, with:

read() on unopened filehandle

I tried using the CGI::upload method, like this:

my $handle_in = $cgi->upload('file_image');

where file_image is the name of the CGI param. But $handle_in is then undef. (I have checked that $cgi->param('file_image') does return the filename.)

Any help gratefully appreciated.

Replies are listed 'Best First'.
Re: Getting a filehandle for uploaded file
by cdarke (Prior) on Oct 20, 2009 at 13:01 UTC
    where $fh was simply the name of the uploaded file.

    I don't think so. From the doc:
    perldoc -f read read FILEHANDLE,SCALAR,LENGTH,OFFSET read FILEHANDLE,SCALAR,LENGTH Attempts to read LENGTH *characters* of data into variable SCALAR from the specified FILEHANDLE...
    You must have got the filehandle from somewhere. Note that upload takes the name of the file, not the name of the parameter which holds the filename.

    Update: Scratch last sentence. It is not true for $cpi->upload. See Bloodnok's post below.
      Thanks for the swift reply. I'm not sure I agree with your comment about CGI::upload though. According to man CGI:
      CREATING A FILE UPLOAD FIELD ... print filefield(-name=>'uploaded_file', ... When the form is processed, you can retrieve the entered filename by c +alling param(): $filename = param('uploaded_file');
      i.e. param is called with the name of the field.

      Then it says:

      The filename returned is also a file handle... # Copy a binary file to somewhere safe open (OUTFILE,">>/usr/local/web/users/feedback"); while ($bytesread=read($filename,$buffer,1024)) { print OUTFILE $buffer; }
      I have also tried the no strict trick mentioned there, but it didn't help. Have also checked it's not browser-dependent.
Re: Getting a filehandle for uploaded file
by Bloodnok (Vicar) on Oct 20, 2009 at 13:44 UTC
    The code snippet in CGI (in PROCESSING_A_FILE_UPLOAD_FIELD) tells us:
    $lightweight_fh = $q->upload('field_name'); # undef may be returned if it's not a valid file handle . . .
    Hence the problem you're seeing is not entirely unexpected - by Lincoln Stein i.e. the module author, anyway;-)

    A user level that continues to overstate my experience :-))
      I noticed that too. So what's the alternative?

        One would think the user didn't upload a file or an error occured (too big?). You can use

        defined($file_from_upload) && defined(fileno($file_from_upload))
        to determine if the param was supplied and that it was supplied as a file upload.
        Hmmm, maybe this will be of use ... to us both ;-)

        A user level that continues to overstate my experience :-))
Re: Getting a filehandle for uploaded file
by bv (Friar) on Oct 20, 2009 at 15:15 UTC

    Is the problem that you are trying to read from the filename, not the filehandle? From the CGI documentation:

    To be safe, use the upload() function (new in version 2.47). When called with the name of an upload field, upload() returns a filehandle-like object, or undef if the parameter is not a valid filehandle.

    Pulling a quote from Bloodnok's post below:

    If there was a problem uploading the file -- for example, the file was bigger than the $CGI::POST_MAX setting -- $filename will be empty. We can test for this and report the problem to the user as follows:

    So you could test for that, too.

    print pack("A25",pack("V*",map{1919242272+$_}(34481450,-49737472,6228,0,-285028276,6979,-1380265972)))
      I've tried using the upload function. It returns undef, which, according to the man page, means the parameter is not a valid filehandle. But why not? I have a normal looking form field:
      <input type="file" name="file_image" ...
      I've done the test according to your second quote. There's definitely nothing coming back from:
      my $handle_in = $cgi->upload('file_image');
      But it's not a POST_MAX problem. That's set to -1, which means no limit. There's a function called cgi_error(), but that's not returning anything either.

        Did you specify the correct enctype for your form?

        <form enctype="multipart/form-data" method="POST" ...>
Re: Getting a filehandle for uploaded file
by scorpio17 (Abbot) on Oct 20, 2009 at 16:26 UTC
    If I understand correctly, you're switching to a new box/OS. This means you may need to check your web server settings, the permission settings of the directory you're trying to upload to, the user id that the script is running as, etc. There are many things that could cause problems - none of which have anything to do with the perl code used in the upload script!

      Thanks to everybody here. Steve's comment made me go and check the form tag, which had method="action".

      I had achieved that by passing CGI::start_multipart_form some wrong parameters. I was passing a hash (method => 'POST', action => ''). It actually takes a list ('POST', '').

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://802217]
Approved by AnomalousMonk
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (2)
As of 2017-03-29 04:15 GMT
Find Nodes?
    Voting Booth?
    Should Pluto Get Its Planethood Back?

    Results (343 votes). Check out past polls.