1) Of course, remember to use enctype="multipart/form-data" in the HTML form. Obvious but I've forgotten it more than once over the years...
2) To tell CKEditor what URL to send the uploaded file to, I pass the target URL to the CKEditor command which replaces the form <textarea> with a rich text editor:
CKEDITOR.replace( 'form_textarea', { filebrowserUploadUrl : '/upload_file' } );
In my case I did this inside a jQuery "ready" handler:
$(document).ready(
function() {
CKEDITOR.replace( 'form_textarea', { filebrowserUploadUrl : '/upload_file' } );
}
);
3) Map the URL to a mod_perl handler
I'm using object oriented perl handlers, so the relevant portion of my httpd.conf file looks something like:
<Location ~ "^/upload_file$">
SetHandler perl-script
PerlHandler NacreData::Controllers::FormHandler->upload_file
</Location>
This will look different if you're using a procedural handler or mod_request or some such.
4) Require/Use a perl module to do the uploading
The one I got to work is Apache::Upload::Slurp
I installed this with CPAN and used a PerlModule directive in httpd.conf to make sure it was loaded at runtime.
5) Write the mod_perl handler
Here's a cleaned up version of what mine looks like:
sub upload_file( $$ ) {
my ( $self, $r ) = @_;
use Apache::Constants qw( :common );
my $apr = Apache::Request->instance( $r );
$r->content_type('text/html');
$r->send_http_header;
require Apache::Upload::Slurp;
my $Uploader = new Apache::Upload::Slurp;
my $uploads = $Uploader->uploads();
my $upload = $uploads->[0];
my $dir = '/upload_files'; # directory where the uploaded files will go
return unless $upload;
return unless $upload->{data};
# make this into a nice filename, no special chars, no spaces, etc.
my $filename = $upload->{filename};
$filename =~ m{([^\\/]+$)};
$filename = $1;
$filename =~ s/[^.\w]//g;
$filename =~ s/__+/_/g;
$filename =~ s/^_//;
$filename =~ s/_$//;
$filename ||= 'file';
# make sure we don't overwrite another file by the same name
while( -f $dir.'/'.$filename || -d $dir.'/'.$filename ) {
my $ext = '';
if( $filename =~ m/(\.[^.]+$)/ ) {
$ext = $1;
$filename =~ s/\.[^.]+$//;
}
my $d = 0;
if( $filename =~ m/(\d+)$/ ) {
$d = $1;
$filename =~ s/\d+$//;
}
$d++;
$filename = $filename . $d . $ext;
}
my $fh;
$filename = $dir.'/'.$filename;
open ( $fh, '>', $filename ) || die "can't open $filename";
print {$fh} $upload->{data};
close $fh;
# now we return the information about the uploaded file to CKEditor.
# reference passed in from CKEditor. We use this to call back, letting
# the editor know we've don the upload.
my $funcNum = $apr->param('CKEditorFuncNum');
$filename =~ s|^/htdocs||; # path under document root to uploaded file
# you probably need ot change this line -- in my case, since I'm
# running under chroot, the webroot is just "/" and docroot /htdocs
my $hostname = $r->server->server_hostname;
$hostname =~ m{(\w+\.\w{2,4})$};
my $url = 'http://' . $hostname . $filename;
print "<script>parent.CKEDITOR.tools.callFunction( $funcNum, '$url' );</script>";
}