It's a well know fact that Drupal 6 has built in support for private downloads. For those of you that don't, enabling the private downloads feature on Administer > Settings > Site configuration puts Drupal back into control when it comes to file downloads. Enabling this option all file requests are handled via Drupal. So Drupal can do download counting, access checks, ... In the case of public downloads, Drupal never knows when a file (in the files directory) is requested, since your web server is handling these on its own.
A problem in Drupal (now) though, is that you have too choose between one or the other. By default you can't use the private downloads and public downloads method at the same time. "By default" I said, because there's a very simple way to mix both.
Suppose you want to protect some directory in your files folder so its files are only visible to users of a certain role. Let's call that directory 'privatedownloads'. Create a .htaccess file in that folder and put in the following content:
<IfModule mod_rewrite.c> RewriteEngine on RewriteBase /system/files/privatedownloads RewriteRule ^(.*)$ $1 [L,R=301] </IfModule>
This will redirect all calls to this folder to a new path, system/files/privatedownloads. So a call to files/privatedownloads/test.jpg will be redirected to system/files/privatedownloads/test.jpg.
Since this path now doesn't physically exist on your server (it shouldn't), the request will be passed to Drupal. Let's respond to it by implementing hook_menu.
/**
* Implementation of hook_menu().
*/
function your_module_name_menu() {
$items['system/files/privatedownloads'] = array(
'access arguments' => array('access private downloads folder'),
'type' => MENU_CALLBACK,
'page callback' => 'file_download',
'page arguments' => array('privatedownloads'),
);
return $items;
}
As you see, we're passing of the request to file_download, a function that is available in Drupal core and which is normally used for Drupal's default implementation of private downloads. I've also attached a permission to this callback, called access private downloads folder. Now you can go to your permissions page and set this permission for the desired roles.
This all works fine now (we're getting the correct file and the permission are at work), only images aren't displayed as images, pdf files aren't displayed in a pdf reader etc. That's due to an incorrect mimetype. Let's set the correct mimetype using hook_file_download and we're done.
/**
* Implementation of hook_file_download().
*/
function your_module_name_file_download($file) {
$info = image_get_info(file_create_path($file));
return array('Content-type: '. file_get_mimetype($file));
}


