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

I could have sworn I knew how this worked, but apparently I was wrong. I am uploading a file via CGI.pm, and I wish to test if the file exists or if a garbage filename was entered

Here are two scripts that demonstrate the problem. The first just creates a filefield, the second is supposed to test if a real file was entered. If I use a POST method for the form, no error-checking is performed. If I use a GET method, however, the error-checking is activated.

Any idea why this is happening, and how to determine when to GET and when to POST?

part1.cgi

use CGI qw/:standard/; use strict; my $cgi = new CGI; print $cgi->header(), $cgi->start_html(), $cgi->start_multipart_form({ -method => 'GET', -action => 'part2.cgi' }), $cgi->filefield({ -name => 'filename', }), $cgi->submit('Add'), $cgi->end_form(), $cgi->end_html();

part2.cgi

use CGI qw/:standard/; use strict; my $cgi = new CGI; print $cgi->header(), $cgi->start_html(); if (!upload('filename')) { print "We Die"; } else { print "No Die"; }

Replies are listed 'Best First'.
Re: Get vs. POST in CGI.pm
by chromatic (Archbishop) on Sep 22, 2003 at 20:12 UTC

    As far as I know, you can't use GET with a multipart/form-data type request. Why would you want to upload a file in the query string, anyway?

    Use POST for changing state on the server. That includes uploading files.

    (Oh, and you might prefer $cgi->upload( 'filename' ), for consistency.)

      Hi, thanks for the response.

      It's fair enough to say "Don't use GET for uploads." But the thing is, the error-checking doesn't work if I use POST.

      If I enter "blablabla" into the form and use a POST, the output is "No Die". If I change POST to GET (as shown in the posted code) I get "We Die". I want to avoid processing non-existant files, but can only do so if I use a GET, which doesn't make sense to me.

      In other words: why does CGI.pm permit upload(garbage) to not be undef with a POST, while it does enforce it with a GET?

        "In other words: why does CGI.pm permit upload(garbage) to not be undef with a POST, while it does enforce it with a GET?"

        POST requests include a content body in the request headers, GET requests do not.

        Here's a link that you may find useful Difference between GET and POST.

        LR

        Whip me, Beat me, Make me use Y-ModemG.
        How is the error checking not working? It fails when used with a GET. Which it should since it is impossible to upload a file without using POST and multipart/form-data encoding. upload() returns the filehandle or undef if there was a failure.

        Are you saying that upload() always succeeds with POST? What are you trying to cause it to fail? upload does not care about the file name. CGI.pm saves the data in a temporary file. You need to validate the file name if you want; it is accessible through param.

        my $filename = $cgi->param('filename'); my $fh = $cgi->upload('filename'); my $type = $cgi->uploadInfo($filename)->{Content-Type};
Re: Get vs. POST in CGI.pm
by LazerRed (Pilgrim) on Sep 22, 2003 at 20:29 UTC
    Along with the many good CGI links in the Tutorials section, I recommend picking up a copy of CGI Programming with Perl. I just picked up a copy, and though I'm only through chapter 4, I'd say it was money well spent already :-) Personally, I prefer paper media over electronic for study... For me it's just more comfortable.

    As for your question, (as was pointed out above)...

    GET is the standard method for retrieving a doc via HTTP. GET requests are intended to only retrieve resources and should not have side effects.

    POST is used with HTML forms to submit information that may alter data stored on the server.

    The above is highly condensed from chapter 2 of the above book.

    LR

    Whip me, Beat me, Make me use Y-ModemG.
Re: Get vs. POST in CGI.pm
by Hagbone (Monk) on Sep 22, 2003 at 23:26 UTC
    I don't pretend to understand the entire CGI upload intricacies, but I maintain a fair number of upload scripts.

    I'm not sure about the GET Vs POST issue ... my experience with uploads, though, leads me to believe that you can't really test *anything* until the upload process has started, and also to believe that you can't test any thing of substance until the upload process has completed.

    It would seem (ie: something I haven't tried) that you could test/confirm that some type of data is being submitted after the upload starts, but my impression has been that until the entire file is actually uploaded and on your server, it's going to be tough to run any "real" type of tests on the file content.

    I may be way off the mark (and no doubt others will point that out), but it seemed that the responses you got so far weren't really responding to your question.

    Hope this helps ... and I'm hoping others will respond ... I'd like to know how soon in the upload process tests can actually be implemented. I've been living with the assumption that you have to wait until the entire file is processed before any real evaluation can happen.

      I may be way off the mark (and no doubt others will point that out), but it seemed that the responses you got so far weren't really responding to your question.

      I feel that way too: I don't feel like I'm communicating myself clearly. I got wicked explanations of GET vs. POST and great code snippets for doing the validation that I need. So, from a purely pragmatic point of view I'm all good.

      The rub is, I still don't understand why this behaviour is observed. The docs say that upload will only return undef or a valid file-handle. I find that it returns a string rather than undef if I pass it a garbage filename. That wasn't expected behaviour. And, more confusing to me, the behaviour seems to change depending on whether I GET or POST it. Not understanding this bugs me! :)

Re: Get vs. POST in CGI.pm
by shenme (Priest) on Sep 23, 2003 at 04:48 UTC
    I think everybody's a little confused here.   I might be wrong but I think that you were concerned that the filename submitted at the remote client might confuse your program or might somehow be invalid at the CGI host.

    So you were trying to figure out how to get a look at the filename, in order to validate it?   And that got you into wanting to use GET where you could 'see' the parameters.   Which got everybody concerned because everybody _knows_ file uploads require POST.   But then again maybe you were wanting to know _how_ to know if anything really got uploaded to your site.

    Well I hadn't yet played with file uploads and need to soon, so I put together the test program following.   I used the docs for the CGI module to do this.   Using this code you can test out some of your assumptions or ideas.

    Output for me when entering an invalid filename was: (using IE to a Linux/Apache host)
    ----------------------------------------------------
      farquarh.txt                   Latest Fullpath
                                     Latest Filepath
      farquarh.txt                   Latest Filename
                                     Latest Length
                                     Latest Status
      application/octet-stream       Latest Content-type
    
    ----------------------------------------------------
    CGI::POST_MAX is '-1'
    CGI::DISABLE_UPLOADS is '0'
    REQUEST_METHOD is POST
    CONTENT_TYPE is multipart/form-data; boundary=---7d335e13e00e0
    
    Submitting a valid filename resulted in:
    ----------------------------------------------------
      \\data01\users2\budgie\diffs.txt  Latest Fullpath
      \\data01\users2\budgie\           Latest Filepath
      diffs.txt                         Latest Filename
      3566                              Latest Length
                                        Latest Status
      text/plain                        Latest Content-type
    
    ----------------------------------------------------
    
    You can drive yourself nuts if you can't see what's going on, so just display any/every thing you _might_ need to see!

      Thank you for the code (and results) shenme. As I mentioned above, I've used a chunk of this code for my validation and duly noted therein that:

      # Parameter checking motivated by shenme # See: http://www.perlmonks.org/index.pl?node_id=293397

      Much appreciated.