Receiving Uploaded Files (Perl Cookbook, 2nd Edition)

## 21.7. Receiving Uploaded Files

### 21.7.1. Problem

You want a mod_perl handler that processes an uploaded file. For example, an image gallery might let the owner upload image files to the gallery.

### 21.7.2. Solution

Use the Apache::Request module's `$r->upload` and `$r->param` methods from within your handler (assuming the file upload field was called `fileParam`):

>     use Apache::Request;

>     my $TEN_MEG = 10 * 2 ** 20;       # 10 megabytes
>     sub handler {
>       my $r = Apache::Request->new(shift,
>                                    DISABLE_UPLOADS => 0,
>                                    POST_MAX        => $TEN_MEG);
>       $r->parse;
>       my $uploaded_file = $r->upload("fileParam");
>       my $filename      = $uploaded_file->filename;  # filename
>       my $fh            = $uploaded_file->fh;        # filehandle
>       my $size          = $uploaded_file->size;      # size in bytes
>       my $info          = $uploaded_file->info;      # headers
>       my $type          = $uploaded_file->type;      # Content-Type
>       my $tempname      = $uploaded_file->tempname;  # temporary name
>       # ...
>     }

### 21.7.3. Discussion

By default, Apache::Request won't process uploaded file data. This is because the file is read into memory, which might not be released to the operating system once the request is over. If you do enable uploaded files (by setting `DISABLE_UPLOADS` to false), set an upper limit on the size of the file you will accept. This prevents a malicious attacker from sending an infinite stream of data and exhausting your system's memory. The `POST_MAX` value (10M in the Solution code) is that maximum value, specified in bytes.

The `$r->upload` method processes the POSTed file data and returns an Apache::Upload object. This object has the following methods for accessing information on the uploaded file:

Method | Returns
--- | ---
`fh` | Filehandle from which to read the uploaded data
`filename` | Client-supplied filename
`info` | Apache::Table object containing HTTP headers sent by the client
`name` | The name of the form field this file was submitted as
`size` | Size of the uploaded file in bytes
`tempname` | Apache::Request's temporary filename
`type` | Client-supplied content-type of the uploaded file

You can invoke `$r->upload` only once per request, as the first invocation consumes all POSTed data. Sometimes multiple handlers need access to the same uploaded file but can't coordinate among themselves by designating one handler to read the file and save its name somewhere that the others can access. In this case, make each handler use the Apache::Request module's `$r->instance` method to get a request object instead of directly shifting it from the argument list:

>     use Apache::Request;
>     # ...
>     sub handler {
>       my $r = Apache::Request->instance(shift,
>                                         DISABLE_UPLOADS => 0,
>                                         POST_MAX        => 10 * 2**20);
>       # ...
>     }

### 21.7.4. See Also

Writing Apache Modules with Perl and C; Recipe 3.8 in mod_perl Developer's Cookbook; the Apache.pm manpage

Copyright © 2003 O'Reilly & Associates. All rights reserved.