I've also had trouble with this. There's a bit of disconnect between the docs I've read and the behavior I've actually managed to get working. Here's my test code that simply displays the image to the browser:
#!/usr/bin/perl -wT
use strict;
use CGI qw (:standard);
use CGI::Carp qw( fatalsToBrowser );
my $filename;
if (defined($filename = param('filename'))) {
my $upload = upload('file');
print header(-type=>uploadInfo($upload)->{'Content-Type'});
print while <$upload>;
} else {
print header();
print <<HTML;
<html><body bgcolor="#ffffff">
<form method="POST" enctype="multipart/form-data">
<input type="text" name="filename"><p>
<input type="file" name="file"><p>
<input type="submit">
</form>
HTML
}
The big difference in this code is that I used the name of the upload parameter instead of the filename when calling upload(). Contrary to what the Mouse book says, this works for me.
For what it's worth, I'm using CGI.pm 2.68, so this may have changed slightly in a newer version. The only mention of uploads in the ChangeLog is of a one-character bug squashed in 2.74. Your mileage may vary.