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

Hey guys:
I'm getting to the point where I HATE anything having to do with trying to make file upload scripts work. I've tried countless scripts and messed with them innumerable ways, and I still can't get one that uploads multiple files at once with no errors. Not only that, but I've shot WEEKS trying! Tilly wrote this one for me, but I can't get it to upload images properly. Can someone test it on their machine and see if it works for them? Also, what could I be doing wrong? I would be deeply indebted to anyone who can come up with an upload script that works for multiple files and runs on *nix, NT, and 98/95/ME. So far, NOTHING I've seen works.
Stamp_Guy

P.S. I realize that this one isn't crossplatform.

#!/usr/bin/perl -T use strict; use CGI qw(:standard upload); use CGI::Carp; use HTML::Entities; print header(), start_html('Upload Test'), h1('Upload Test'), start_multipart_form(), "Enter how many files to upload: ", textfield("filecount"), br(); for my $i (1..param('filecount')) { print "File $i: ", filefield(-name => "file$i"), br(); } print submit(); for my $file (sort grep /file/, param()) { print p(); my $handle = upload($file); open (IMAGE, ">$handle") || die "Couldn't open $handle: $!"; # I realize that the above line needs to have a dir with write per +missions, etc. my $buffer; while (read($handle, $buffer, 10240)) { print IMAGE $buffer; } unless (defined($handle)) { if ($file =~ /(\d+)/) { print h3("File request $1 did not return a handle\n"); } next; } print p(), h3("Uploaded $handle"), br(), "<pre>"; print encode_entities($_) while <$handle>; print "</pre>"; } close(IMAGE);

Replies are listed 'Best First'.
Re (tilly) 1: Uploads (again!)
by tilly (Archbishop) on Jan 16, 2001 at 07:00 UTC
    The above is not one of the samples I gave you.

    Getting it to work is not hard. See CGI for what my defined test is doing. Figure out how to create debugging output to the browser if you do not have web logs. Note that the indenting has a purpose and fix it to match the logical structure. So on and so forth.

    BTW I am not finishing the example for you. No matter how many times you post the request for me (or anyone else) to do so. This site is for learning to program, no for getting free work done. I have had quite enough iterations on this problem. As far as I am concerned, it is up to you to figure out where your file is trying to go, why it is probably running into permission problems, where you want it to go, and fix it to go to the right place.

      Hey Tilly,

      Please don't get me wrong, I WANT to learn! I'm just fed up because I can't seem to figure it out. I am a total newbie with no programming background, and the only way I know to solve these problems is to read about it and ask. I've been reading all I can get my paws on, but to no avail. That's why I asked. I'm not out here just asking everyone to do my work for me. I got the errors to display to the browser, and here's what I got:

      Couldn't open &lt;UPLOAD&gt;filecount&lt;/UPLOAD&gt;: No such file or +directory at trythis.cgi line 17.
      I went back and checked and sure enough, it's right at the open statement I wrote. I can't seem to figure out what's wrong with it though. I looked up the CGI module, but couldn't find out what the defined test was doing. Where do I look? I want to learn all I can here, I'm just really frustrated right now, because I don't know what to try next. I'm not asking you to complete it for me, I'm asking for you to help point me in the right direction when I'm totally stuck (as I am now). My main question is: What's wrong with my open statement?
      #!/usr/bin/perl -T use strict; use CGI qw(:standard upload); use CGI::Carp 'fatalsToBrowser'; use HTML::Entities; print header(), start_html('Upload Test'), h1('Upload Test'), start_multipart_form(), "Enter how many files to upload: ", textfield("filecount"), br(); for my $i (1..param('filecount')) { print "File $i: ", filefield(-name => "file$i"), br(); } print submit(); for my $file (sort grep /file/, param()) { print p(); my $handle = upload($file); open (IMAGE, ">$handle") || die "Couldn't open $handle: $!"; my $buffer; while (read($handle, $buffer, 10240)) { print IMAGE $buffer; } unless (defined($handle)) { if ($file =~ /(\d+)/) { print h3("File request $1 did not return a handle\n"); } next; } print p(), h3("Uploaded $handle"), br(), "<pre>"; print encode_entities($_) while <$handle>; print "</pre>"; } close(IMAGE);
      P.S. This is the code you sent me with only a couple changes.
        It isn't a surprise to you that the file "UPLOAD" doesn't exist and thus can't be opened on Line 17, right? Its a good idea esp. w/ us novices, it to comment every single goldurn close bracket w/ what its closing (even just 2 lines) e.g.
        for my $file (sort grep /file/, param()) { print p(); my $handle = upload($file); open (IMAGE, ">$handle") || die "Couldn't open $handle: $!"; my $buffer; while (read($handle, $buffer, 10240)) { print IMAGE $buffer; } # while read or for my file sort ??? unless (defined($handle)) { if ($file =~ /(\d+)/) { print h3("File request $1 did not return a handle\n"); } # if $file =~ \d next; } # unless def $handle print p(), h3("Uploaded $handle"), br(), "<pre>"; print encode_entities($_) while <$handle>; print "</pre>"; } # for my $file sort
        So, if handle isn't defined, why print to it? Why don't you have -w up there? How about sort grep /file\d+/ to get only the file0-9+ params? Why not put a few debugs in along the way: print STDERR "Trying file $file\n"; before the upload stmt. Maybe an "if (-s $file)" to be sure $file exists. As the tilly said, its not about getting this one to work, its about learning how to get scripts in general to work. You know UPLOAD isn't the file, so how did you get the name? From your for sort grep loop. What else is that returning? Use STDERR to put debug to the error logs so you can watch as the script progresses.

        I like to use
        print STDERR "trying file $file in forloop\n" if $debug > 3;
        and then use "my $debug = X" as needed. You'll often find you need to turn debugging back on, and by using different levels for different levels of detail, you can leave all your debugs in (my $debug = 0) and turn on those you need as you change stuff.

        a