8.5.x file.api.php hook_file_download($uri)
8.0.x file.api.php hook_file_download($uri)
8.1.x file.api.php hook_file_download($uri)
8.2.x file.api.php hook_file_download($uri)
8.3.x file.api.php hook_file_download($uri)
8.4.x file.api.php hook_file_download($uri)
8.6.x file.api.php hook_file_download($uri)
4.7.x core.php hook_file_download($file)
5.x core.php hook_file_download($file)
6.x core.php hook_file_download($filepath)
7.x system.api.php hook_file_download($uri)

Control access to private file downloads and specify HTTP headers.

This hook allows modules enforce permissions on file downloads when the private file download method is selected. Modules can also provide headers to specify information like the file's name or MIME type.


$uri: The URI of the file.

Return value

If the user does not have permission to access the file, return -1. If the user has permission, return an array with the appropriate headers. If the file is not controlled by the current module, the return value should be NULL.

See also


Related topics

6 functions implement hook_file_download()

Note: this list is generated by pattern matching, so it may include some functions that are not actually implementations of this hook.

file_file_download in modules/file/file.module
Implements hook_file_download().
file_module_test_file_download in modules/file/tests/file_module_test.module
Implements hook_file_download().
file_test_file_download in modules/simpletest/tests/file_test.module
Implements hook_file_download().
image_file_download in modules/image/image.module
Implements hook_file_download().
image_module_test_file_download in modules/image/tests/image_module_test.module
@file Provides Image module hook implementations for testing purposes.

... See full list

1 invocation of hook_file_download()
image_file_download in modules/image/image.module
Implements hook_file_download().


modules/system/system.api.php, line 3006
Hooks provided by Drupal core and the System module.


function hook_file_download($uri) {

  // Check if the file is controlled by the current module.
  if (!file_prepare_directory($uri)) {
    $uri = FALSE;
  if (strpos(file_uri_target($uri), variable_get('user_picture_path', 'pictures') . '/picture-') === 0) {
    if (!user_access('access user profiles')) {

      // Access to the file is denied.
      return -1;
    else {
      $info = image_get_info($uri);
      return array(
        'Content-Type' => $info['mime_type'],


markj’s picture

Note, in D6, this function returns a simple array listing the headers as strings. In D7, it returns an associative array, with the header fields as keys and the header values as values.

b.ravanbakhsh’s picture

Example for check some logic when content type field is file attached to a node
function hook_file_download($uri){
global $user;
$result = db_query('SELECT id
FROM `file_managed` m, file_usage u
WHERE m.fid = u.fid
AND u.`type` = :type
AND uri = :uri', array(':type' => "node", ':uri' => $uri))
$node = node_load($result);
// doing some logic ....
return array('Content-Type' => file_get_mimetype($uri));

agileadam’s picture

 * Implements hook_file_download().
function mymodule_file_download($uri){
  $query = db_select('file_usage', 'fu');
  $query->addField('fu', 'id');
  $query->join('file_managed', 'fm', 'fm.fid = fu.fid');
  $query->condition('fm.uri', $uri, '=');
  $query->condition('fu.type', 'node', '=');
  $result= $query->execute();

  foreach($result as $record){
    // If this file is used in a research node where Display File(s) is not checked, don't allow user to view file
    $node_wrapper = entity_metadata_wrapper('node', node_load($record->id));
    if ($node_wrapper->type->value() == 'research' && $node_wrapper->field_research_displaydocs->raw() != 1) {
      return -1;

  $info = image_get_info($uri);
  return array('Content-Type' => $info['mime_type']);
pdcarto’s picture

file_prepare_directory checks to see if this private file is controlled by this module. It's a way of figuring out if this file is interesting to you and if you want to control access to it. I think most of the time you would not check this because most of the time you're trying to modify file access that was set by another module.

vishal.shirguppi’s picture

The hook_file_download fires on every Partial Content 206 HTTP request resulting my custom module code to show duplicate downloads.
I tried drupal_get_http_header($name = NULL) but apparently that has been kinda deprecated and returns nothing.

Any inputs would be really appreciated.