In Apache .htaccess
, I have below block to force download.
<If "%{QUERY_STRING} =~ /fileName=/">
ForceType application/octet-stream
Header set "Content-disposition" "attachment; filename=download.doc"
</If>
This works fine. Now I need to make the filename be the value of query string key "fileName".
I know how to do this in Nginx. Below is the code.
if ($arg_fileName) {
set $fname $arg_fileName;
add_header Content-Disposition 'attachment; filename="$fname"';
}
How to do this in Apache .htaccess
?
You could do something like this with the help of mod_rewrite:
RewriteEngine On
# Save value of fileName URL param in environment variable FILENAME
RewriteCond %{QUERY_STRING} (?:^|&)fileName=([^&]+)
RewriteRule ^ - [E=FILENAME:%1]
# Conditionally set header only if FILENAME is set and use this in the header itself
Header set "Content-Disposition" "attachment; filename=\"%{FILENAME}e\"" env=FILENAME
([^&]+)
- Note, however, that you might want to restrict the regex used to match the fileName
parameter value, since not everything is necessarily permitted in the filename argument of the HTTP response header. This can vary by browser and modern browsers do support more. Note also that the value grabbed from the QUERY_STRING
is already URL-encoded. So, maybe something like ([\w.-]+)
would be sufficient instead to match just a-z
, A-Z
, 0-9
, _
, .
and -
?
The env=FILENAME
argument results in the header only being set when the FILENAME env var exists, so this negates the need for the <If>
expression.
ForceType application/octet-stream
This isn't strictly necessary to trigger a download, it is the Content-Disposition: attachment
header that does this in any remotely modern browser. In fact, it is not necessarily recommended to send the application/octet-stream
mime-type for all responses. You should be sending the correct Content-Type
header for the resource being sent.