Usually when a user goes to a file URL, the file will show in the browser if the browser supports it. Image files like png, gif, jpg almost always show in the browser. Archive files like zip, tar, and gzip almost are always downloaded. Some file types show up in some browsers but not others, svg files will display in Firefox and Safari, but not Internet Explorer 7. Internet Explorer will usually try to show Microsoft Word files (doc and docx) in the browser, while most other browsers will download it.

Update 2020:
Please note, that in modern browsers you can easily solve this in the a href by adding a download attribute:
<a href="/images/example.jpg" download>

See: https://www.w3schools.com/tags/att_a_download.asp for details.

To add consistency or to force certain files to download, you can fix this by simply adding an .htaccess file to the files directory. Note this only works with Public downloads and an Apache web server.

Set up a Specific Files to Download

  1. First, setup your file field so that it saves into a separate directory. This will make it so that you will only force certain files to download and not affect the rest of the files on your Drupal site. Visit Administer -> Content management -> Content types (admin/content/types). Click "Manage fields" on the type that you want files to be forced to be downloaded. Add or edit a file field, under the "Path settings" fieldset, set a path for your files to be uploaded.

    Now files uploaded to that field will be saved in a separate folder under your sites files directory.

  2. FTP to your site and create a file named .htaccess in your files directory. Usually this will be sites/default/files/[name of the subdirectory from step 1]. In that file put the following lines:
    <FilesMatch "\.(?i:doc|odf|pdf|rtf|txt)$">
      Header set Content-Disposition attachment
    </FilesMatch>
    

    This particular example will force files with doc, odf, pdf, rtf, or txt to download instead of being shown in the browser.

  3. Upload a few files and (using the "Generic files" display setting), the files will be downloaded when the user clicks on the link.
  4. You may need to load mod_headers in Apache2 for this to work.
    Assuming you have root access it can be done as follows:
    # a2enmod headers
    # /etc/init.d/apache2 reload
    

Comments

harkonnen’s picture

Or alter mime type

AddType application/octet-stream .pdf
whallify’s picture

I just spent a good hour trying to troubleshoot this.

End result was that

<FilesMatch "\.(?i:pdf)$">
      ForceType application/octet-stream
      Header set Content-Disposition attachment
</FilesMatch>

as recommended above worked for everything.

Just the Addtype... doesn't seem to work for IE8 on Windows 7. I had that on mine, and what was annoying was it would work in Firefox, Safari but not IE8. Instead, I'd just get the annoying 'File does not begin with %PDF' error, *or* IE would try to view the file in the browser, and it would just lock up.

What was interesting was that if I had no .htaccess file at all, all browsers worked fine.

I needed an .htaccess file to restrict downloads of PDF's to only people who had registered on the site, so I needed their REFERER to be a specific page. But without any .htaccess, PDF is viewable by all browsers. Putting in the .htaccess file that had ReWrite on would cause problems.

Once I added the above lines, it started working to force download on all the browsers. Strange.

Thanx much!

shriji’s picture

I did the same thing for my mp3 files and all my mp3s stopped working because of following error that i collected from access.log file:

127.0.0.1 - - [26/Sep/2010:22:07:10 -0400] "GET /sites/default/files/flash/temp/BhaktaCharitra/KabeerDasJi/col.1900.01.01.z%20www.brajdhamsewa.org.mp3 HTTP/1.1" 500 541

when I remove the file everything starts working but the mp3 file would play instead of download.

Any idea??

Thanks

janzell’s picture

I got this through this code.


ForceType application/pdf
Header set Content-Disposition attachment

from this blog.

http://mushutricks.blogspot.com/2010/11/forcing-pdf-to-download-in-httac...

indikaaruna-1’s picture

This is working for multiple files.
<FilesMatch "\.(?i:doc|odf|pdf|rtf|txt|jpg|png)$>
AddType application/octet-stream doc odf pdf rtf txt png jpg
</FilesMatch>

jwrosenthal’s picture

I understand wanting to force a user to download a file because that is your desired effect, however I believe it should be left up to the user and their custom settings. As a user if I'm clicking on a jpg and it prompts for download rather than opening in my browser or whatever application I have set as default I will not only feel confused, but will be a bit upset being forced to do more work. Think about if this is a real necessity before forcing the user to do what YOU think they want.

BrianLewisDesign’s picture

Force Download is Useful... I am making a download images page, for clients to download print images...

If you Do NOT set it to download, the client has to click the image link, go to the image page, right click the image, click save, wait for it to load, click the back button.

If you Do set it to download, they click the download link for each one they want, done, images queue and download automatically.

Jeremy Byrne’s picture

The D6 File Force module (http://drupal.org/project/file_force File) may be of value here.

marcoka’s picture

file_force is an abandoned project :(

how to do this with private downloads?

arski’s picture

File Force is not abandoned at all :)

felipesluz’s picture

To force some extensions and some files to download, use this recent Module:

http://drupal.org/project/download_file

DownloadFile is a module to direct download files or images.

Bye.

arski’s picture

by the way, download_file is basically a copy of file_force, with slightly less options, so go for the latter ;)

sapox’s picture

Everybody forgot to mention that this code will work (in apache at least) only if you have the headers_module (or mod_headers) enabled.
Therefore, for apache 2, enter on the linux command-line:

$ sudo a2enmod headers

And restart the server.

skagentech’s picture

For anyone that's looking for a .htaccess forced download on all file types..

<Files ~ "\.*$">
Header set Content-Disposition attachment
</Files>

Good luck!

erinclerico’s picture

I set this script up - it looks secure, it can log and I like the way it allows limiting the types of files that can be downloaded:

http://www.zubrag.com/scripts/download.php

So again just construct a link to bounce a filename off this script - you are outside of the Drupal framework but this is pretty easy to set up.

Your milage may vary...

Erin Clerico

Drupal Developer

http://redjupiter.com

stoan’s picture

I can report this solution works, I even did it on my Joomla site, Just created the .htaccess file as advised with the extensions I needed such as .mp3 ,I added the .htaccess on the file directory and works 100% :-) been looking for a simple solution for a while. Thanks for this.

Tested on Google Chrome.

Khumbu’s picture

Will this work with amazon S3?

el paraje’s picture

thanks for the solution, had to change one extension to gpx. The Firefox "save" or "open with" pop up appears now.

cropis’s picture

Hi, I want to know how to force the download for links outside my own website. I have some links the clients shorten in my URL shortening website but some of then are from file and not authentic websites. http://crop.is

bobbins’s picture

Hi not sure if off topic but I wanted a certain content type (private file upload) to always download rather than show the node with the link on it so I added a hook_node_view checking for the content type and then set headers to force download.

       //If this node is a file then get it to download directly
	if($node->type == 'file')
	{
		//Create a link to the Drupal private path
  		$file = "http://sitename.com".str_replace('private://', '', $node->field_file['und'][0]['uri']);
		
  		header('Content-Type: ' . mime_content_type($file));
		header('Content-Length: ' . filesize($file));
		header("Content-Transfer-Encoding: Binary"); 
		header("Content-disposition: attachment; filename=\"" . basename($file) . "\"");
		readfile($file);
		
		die();
	}
PunamShelke’s picture

Hi,

I have created webservice to download the private file but its not working,
any suggestion how we can do this?

ruchirapingale’s picture

Hi,

Drupla 8 also having same code like drupal 7.
1) Add the following code in sites\default\files\ .htaccess

             <FilesMatch "\.(?i:doc|odf|pdf|rtf|txt|jpg|png)$>
                AddType application/octet-stream doc odf pdf rtf txt png jpg
            </FilesMatch>
           

2) Restart apache