Recipe 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:
|
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
|