At 2:55 PM -0700 2002-05-24, Chris Angelli wrote:
>difficulty doing something very simple.   For some
>reason I can't get file uploads to work. I am doing
>nothing fancy, but my uploads just don't work.

I moved the rest of Chris's post to the end, in case someone wants to 
look at it.

I've had several file upload sites going for a few years. The code 
you quoted seems slightly different from what I'm now using. I 
started from Lincoln Stein's book, but I know my stuff has evolved 
over the years to handle various contingencies.

Below is an excerpt that covers the basics. It's taken from a 
subroutine that is in my standard library for dispatch via a CGI 
script's state machine, but I've tried to simplify it down to what's 
important.

A few other comments, if I may:

1. Your comment that 'use constant' isn't working is of concern. Do 
you have other CGIs working on this setup?

2. My development site is a vanilla OS X 10.1.4 w/ developer tools 
(Perl 5.6.0, CGI.pm 2.56) installed. I'm not running mod_perl on it, 
and mod_perl affects the persistence of variables, so there might be 
something the look for there.

3. We get the handy computing experience of the Mac interface using 
BBEdit, one of whose benefits is direct Perl syntax checking. 
However, in a web context, there is really no way to avoid checking 
your webserver error log, if you're serious about your work. (Even 
using strict.pm and the '-w' switch won't tell you everything.) In 
this modern age, one may simply open a Terminal window, and type in 
the command

% tail -f -n20 /private/var/log/httpd/error_log

and get the last 20 lines of their ht error log, continuously 
updating itself as a script is tested on their server.

Ain't it the OS X life?

If at first you are dismayed to see MANY lines of error messages 
scroll by every time you call your script, just remember that 
mistakes are our friends. For hardcore logic poets, watching an 
eventless error log during testing has a certain satisfaction...

4. Here's my example:

## File upload example

# Excerpted from a production script
# deployed on Solaris, Mac OS X, NT, & Win 2000 servers

# Utilize 'for' loop for control flow
# In this case there is only one file upload field in the HTML form.
# It's named 'img_file' -- the user has uploaded an image file.
# The hash %input_vals holds cleaned-up input obtained via CGI.pm
# For clarity, methods from CGI.pm are shown in the form CGI::method()
# Other methods here are from my modules, but their names suggest what they do
# Sorry about the outermost 'if' structure -- it's a vestige.

for my $file_fld ('img_file') {
     if ($input_vals{$file_fld} ne '') {
         # Get the file upload object directly from CGI.pm
         my $image_file  = CGI::param($file_fld);

         ## Check file type and generate a conforming file suffix
         my $type    = CGI::uploadInfo($image_file)->{'Content-Type'};
         my $suf     = '';
         {
         local $_ = $type;
         $suf = /gif/i ? 'gif' :
                  /jpeg/i ? 'jpg' :
                      /png/i ? 'png' :
                           '';  # $suf ends up blank if no match
         }
         ## Not a desired file type? Ask the user again
         unless ($suf) {
             oops('wrong_file_type', $type) # script exits here
         }

         ## Check file size
         # set maximum file upload size, in kB.
         my $max     = 100;
         # start a counter
         my $length  = 0;
         # puff a buffer
         my $buf     = '';
         # read through the tmp file, chunking 1 k at a time
         while (read($image_file, $buf, 1024)) {
             $length++;
         }
         ## File too large? Ask the user again
         if ($length > $max) {
             oops('file_too_large', $length) # script exits here
         }

         ## OK. Save the file
         # Rewind
         seek $image_file, 0, 0;
         # Make up a name for the permanent file, using suffix from above.
         # For security and glitch-avoidance,
         # don't accept user input for a filename
         my $img_file_name = "/path/images/$user_id.$suf";
         # Open the permanent file
         open IMAGE, ">$img_file_name" or oops('file_write_failed', $!);
         # Write to the permanent file from the tmp file
         while (read($image_file, $buf, 1024)) {
             print IMAGE $buf;
         }
         close IMAGE;
         $input_vals{$file_fld} = "$user_id.$suf"; # non-tainted filename
     } else {
         # This prevents overwriting existing filename if nothing new submitted;
         # only needed for file uploads because other types of input field allow
         # use of defaults. HTML file upload fields don't accept default values.
         delete $input_vals{$file_fld}
     }
}
# After this, %input_vals is handed to the database interface
# to create or update this user's record
# The temp file is auto-deleted

## End of Example

HTH

1;

   - Bruce

__bruce_van_allen__santa_cruz_ca__


At 2:55 PM -0700 2002-05-24, Chris Angelli wrote:
>here's the stolen code snippet: (It might look
>familiar to readers of 'CGI programming with perl')
>my $file     = $q->param ("file") || error ($q, "No
>file received.");
>my $filename = $q->param ("filename") || error ($q,
>"No filename entered.");
>my $fh       = $q->upload($file);
>my $buffer   = "";
>while (read ($fh, $buffer, $BUFFER_SIZE)) {
>   print OUTPUT $buffer;
>}
>
>close OUTPUT;
>
>When I try to read from $fh, I get nothing.  Also, I
>tried to see where/what was going on with the temp
>file that CGI.pm creates, but
>
>my $tmpfile = $q->tmpFileName($file);
>
>returns nothing.
>
>and so does
>               my $info = $q->uploadInfo($assetParamName);
>               my $ctype = $info->{'Content-Type'};
>
>Has anyone seen this type of behavior before?  Is
>there anything obvious that I should/shouldn't be
>doing?
>
>I should note that for some (probably unrelated
>reason) use constant doesn't work either.
>
>My environment:
>
>OSX  10.1.4
>APACHE Apache/1.3.20 (Darwin)
>mod_perl 1.26
>CGI.pm 2.752

-- 

   - Bruce

__bruce_van_allen__santa_cruz_ca__

Reply via email to