3

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?

3

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); 
| improve this answer | |
  • Nice answer (+1). Just a couple of potential code tidies... $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. – MrWhite Apr 21 '16 at 23:28
2

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.

| improve this answer | |
2

Server side:

Add this to your .htaccess file:

AddType application/octet-stream .pdf

Client-side:

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.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.