December 9, 2011

Working with Drupal's private files

On a recent project at Fuse we had to provide access to file uploads through Drupal only to users that were authenticated. One way to do this is to use the private files feature that Drupal core comes with. Something we hadn'€™t done until now.

The initial setup of a private files structure is relatively straight forward. I'€™ll reference the Drupal.org docs (http://drupal.org/documentation/modules/file) for details on how you can setup a private file structure for your site. In addition you'€™ll want to create a content type with a file upload field and in the configuration screen for the file field, set the upload destination to your private directory.

Once that'€™s done, you'€™ve successfully implemented a private file repository. Now comes the part that was lacking in direction and documentation. Giving access to private files to your authenticated users .

As far as we could tell, you'€™ll need to create a custom module and implement the magical hook_file_download_access_alter()* hook. This hook allows you to alter the access permissions for a file download. Since the default is set to Deny as the files are private, we'€™ll have to open that up a bit.

*One odd caveat to using this function. The API states that four parameters are passed through to this hook. However, only the first three are passed through at this point. You can read up on the issue here (http://drupal.org/node/1143460).

function yourmodule_file_download_access_alter(&$grants, $field, $entity_type) { $grants = TRUE; }

So in its simplest form, this will now allow access to any private file to all users requesting the file. Even logged out users! To correct that we'€™ll want to add our own logic to determine whether access should be permitted.

function yourmodule_file_download_access_alter(&$grants, $field, $entity_type) { global $user; if ($user->role == 'authenticated') { $grants = TRUE; } }

This will now restrict the file to any authenticated user. You could go one step further and check if the user in question is the "€œowner"€ of the node that the file was uploaded to. Unfortunately, this is made a bit more difficult since $entity is not passed through to this hook.

function yourmodule_file_download_access_alter(&$grants, $field, $entity_type) { global $user; if ($user->roles == 'authenticated user') { $grants = TRUE; } }

The sky'€™s the limit when it comes to what you want to use to determine the accessibility of your private files. If you really wanted to mess with someone you could restrict access to the files to only odd numbered minutes.

function yourmodule_file_download_access_alter(&$grants, $field, $entity_type) { if (!date('i') % 2) { $grants = TRUE; } }