Rather than using a link like the following in a html page:
<a href="http://www.somesite.com/path/to/file.pdf">Display file</a>
I would like to obfuscate the path to the file from the remote user. So I wrote a Perl CGI script to do so, a simplified version is shown here:
#!/usr/bin/perl -T
use strict;
use warnings;
use CGI qw/:all/;
my $basepath = '/some/path/to';
my $f = param("f") || '';
($f eq '') && die;
my $path = "$basepath/$f.pdf";
open(PATH, "<$path") || die;
binmode PATH;
print header(-type => "application/pdf",
-target => "$f");
print;
while (<PATH>) {
print($_);
}
close(PATH);
I save this script as $htdoc/cgi-bin/getpdf.cgi, then use the following URL in the html file instead:
<a href="http://www.somesite.com/cgi-bin/getpdf.cgi?f=file">Display file</a>
This script works, but the file name shown to the user is the name of the script (getpdf.cgi), not the name of the file being served (file.pdf). This is not very good because no matter what file is being served, the file name is getpdf.cgi. I would like it to be the actual file name (which is passed as the f= param in the URL, with the .pdf extension appended).
I tried using the following header() instead of what's in the script above:
print header(-type => "application/pdf",
-target => "$f",
-attachment => "$f.pdf");
Note the added -attachment line. This does override the file name to file.pdf, but it causes the browser to open a "Save as" dialog window rather than just displaying the file.
How to solve this problem?
UPDATE: TUrns out I needed to have the following in my header:
Content-Type: application/pdf
Content-Disposition: inline; filename="$f.pdf"
The first header line is easily generated with CGI.pm's header() method:
print header(-type => 'application/pdf');
But CGI.pm does not give me a way to generate the second line, at least not the version that's on the server. If I use the following code:
print header(-type => 'application/pdf', -attachment => "$f.pdf");
Then the generated header looks like this:
Content-Type: application/pdf
Content-Disposition: attachment; filename="$f.pdf"
Having "attachment" causes the browser to pop up a "Save as" dialog box which I don't want to be the default behavior. I want "inline", but header() has no parameter for it.
I also found that I cannot use multiple header() calls, that seems to cause everything after the first one to be ignored.
So the solution is not to use header() at all, but just explicitly call print() to output the needed header lines, plus one blank line to signify end-of-header.
I tested this on Chrome, Firefox and IE. They work as intended in displaying the PDF file. If I then try to download it, the correct file name is provided as default on Chrome and Firefox. On IE it still shows the default file name as getpdf.cgi.
At this point I think I'll just chalk it up to be yet another IE "bug" and leave it at that.