I've finally come up with a work around for this problem.
Although the RFC 2183 shows that a filename parameter can be used for both attachment and inline for the Content-Disposition header field, it seems that browsers ignore the filename parameter when inline is used but rather try to work out what the filename should be based on the URL. If the URL has no query string then the part of the URL that follows the last / seems to be used as the filename.
I have changed the links that download the protected PDF documents to use nice URLs that don't contain a query string and use mod_rewrite with a .htaccess file to convert those nice URLs to execute the correct script with the correct parameters:
Old link:
index.php?page=secure-area/download&file=document.pdf
New Link:
file/secure-area/download/document.pdf
.htaccess:
RewriteEngine On
RewriteRule ^file/secure-area/download/(.*)$ index.php?page=secure-area/download&file=$1 [L]
The script used to actually send the file is the same as I used before (note the example in the question uses Content-Disposition: attachment rather then Content-Disposition: inline to demonstrate browsers saving the document with the correct filename when not inline).
// check security, get filename from request, prefix document download directory and check for file existance then...
header('Content-Type: application/pdf');
header('Content-Disposition: inline; filename="' . basename($file) . '"');
header('Content-Transfer-Encoding: binary');
header('Content-Length: ' . filesize($file));
header('Connection: Close');
set_time_limit(0);
readfile($file);
Now the PDF document opens inside the browser and when saved the default filename is
document.pdf
and not
http___example.com_index.php_page=secure_area_download&file=document.pdf
IE 7 converts spaces in the filename to +'s and single quotes to %27's when saved (Firefox doesn't), I would like to stop that from happening but for the meantime I'm happy with what I've got.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…