I have an apache server with access to a directory, eg /downloads/pdf/
How can I tell the sever when a user requests http://example.com/downloads/pdf/example.pdf
not to open it directly, but downloading it?
Webmasters Stack Exchange is a question and answer site for pro webmasters. It only takes a minute to sign up.
Sign up to join this communityI have an apache server with access to a directory, eg /downloads/pdf/
How can I tell the sever when a user requests http://example.com/downloads/pdf/example.pdf
not to open it directly, but downloading it?
I'm guessing you are not only looking into how you can download A file, but also concerned about how to do that for every file in a specific folder on the server without having to change the link itself on every page.
If you have write access to the folder where the files are (download) and to the web server, you could add an .htaccess
in that folder with a rewrite rule that redirects every call on that folder to a PHP file.
/downloads/.htaccess
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule ^(.+)$ /downloads/index.php?download=$1 [L]
</IfModule>
This should redirect every call to a file inside downloads
called index.php
.
On this file you can use $_GET["download"]
to check the path of the file being requested and then do what w3dk suggested.
/downloads/index.php
(something like this, I haven't tested this exact code)
$path = $_GET["download"];
$folder = substr($path,0,strrpos($path,'/'));
switch ($folder) {
case 'pdf':
// specify content type
break;
case 'jpg':
// specify content type
break;
...
}
header('Content-Disposition: attachment; filename='.$path);
header('Content-Length: '.filesize($path));
flush(); // this doesn't really matter.
$fp = fopen($path, "r");
while (!feof($fp))
{
echo fread($fp, 65536);
flush(); // this is essential for large downloads
}
fclose($fp);
$folder = dirname($path)
and, unless you have a specific requirement to send the file in chunks, readfile($path)
will do the same as your fopen()
.. fread()
.. fclose()
loop.
How can I tell the sever...
You are "telling" the browser (user-agent), not the server.
You basically need to send the appropriate HTTP response headers. Specifically the Content-Disposition
and possibly the Content-Length
headers.
For example:
Content-Disposition: attachment; filename=example.pdf
Content-Length: 8809
The filename
argument is optional, but allows you to specify the default "Save As" filename.
Contrary to what you sometimes see suggested. You should send the appropriate Content-Type
header for the resource (as you would normally do). That is application/pdf
for PDFs and image/jpeg
for JPG images. Don't try to fool the browser into downloading a resource by telling the browser that it's something it doesn't know how to handle. eg. application/octet-stream
.
Add this to your .htaccess file:
AddType application/octet-stream .pdf
It is simple and it consists in using the HTML5 download
attribute. This works both with images and pdf files as you requested.
Example:
<a href="http://example.com/downloads/pdf/example.pdf" download> Download</a>
In the same way, you can run this demo concerning images from W3School website.
You may check here the list of browsers and their versions that support this attribute.