Your main problem is that you're only outputting the header and not the contents of the file itself. If you're going to output your own mime-type header like this, you would then need to open the file in question (use binmode()) in chunks, outputting those chunks to the browser as they are read.
my $buffer;
open(DOWNLOAD, "< /path/requested_file") or die "Could not read file:
+$!";
binmode(DOWNLOAD);
while( read(DOWNLOAD, $buffer, 4096) ){
print $buffer;
}
close(DOWNLOAD);
"Forcing a download" is really a function of the browser, and results from the browser's decision on how to handle the particuar mime type you send. You may want to also try "application/binary" in addition to the "application/octet-stream".
In your code, I think that using 'join' is a bit of overkill when you can concatenate the strings as
my $load_file = $dl_file . $file;
Also, I would get rid of the start_html and end_html bit -- unnecessary, and I suppose could mess up your headers, too.