File download in Drupal

The attached ebook, Files in Drupal, has been expanded and updated to account for changes in Drupal 6.
Update, May 10th, 2008.

You'll find in the pdf document attached to this posting “10 things you ought to know” about file download in Drupal, from a developer’s perspective. This small guide provides sample code, recipes, concise yet complete explanations, tricks, and a thorough coverage of the module hook function file_download. The document is 6 11 16 17 pages long, it has been expanded and updated to account for changes in Drupal 5 and 6. I also added a 'funny' cover to the book. (My modest attempt at humour.) Typos are corrected pretty much on a daily basis... If you’ve downloaded the document before May 17th, 2008, please redownload it.

Content at a glance

  1. About the permission “view uploaded files”, p.2
  2. No records of uploaded files being downloaded, p.4
  3. For module developers : the HOOK_file_download, p.5
  4. File toolkit with examples (using clean URLs), p.9
  5. When using the private download method, p.11
  6. Changing when & how the attachment table is displayed, p.12
  7. Uploading two files with the same name, p.14
  8. A word on hot linking, p.15
  9. Images and links in nodes : doing it by hand, p.16
  10. Browsing a folder for specific files the Drupal way, p.17


Summary of the “10 things you ought to know about file download in drupal” :

  1. The problem : Using Drupal’s in-core upload module, and no “node access control” contributed module, anonymous users can either download all files attachments, or none of them. The trick : in the case where anonymous users are forbidden access to uploaded files, automatically generate a message to inform them that one or more files are attached to a post. Involves : modifications to node.tpl.php and the use of Drupal’s function format_plural(). This section provides sample code safe to copy from the pdf to your template file in your favorite text editor. download permission

  2. The problem : Drupal’s core upload module does not keep track of file downloads, even when the download method is set to private. The trick : install the contributed module download_count. This module writes a descriptive message in your logs whenever a person or robot is attempting to download an attached file. The module also keeps a record of total download hits, and last download time, to display on a dedicated page and in nodes (to which these files are attached). In your tracking of file downloads, you can chose to disregard file attachments with particular extensions. download statistics

  3. This third point explains when, why and how to use the hook function file_download. Using this function, we can :

    • Keep track of file downloads — and this section tells us what files the function can do bookkeeping of.
    • Allow files that aren’t recorded in the upload module’s table {files} to be downloaded by returning an appropriate HTTP header for them.
    • Block the download of particular files of our chosing.

    This section provides two code examples : one in which we allow the download/display of an image that sits outside the web root, and an other in which we allow the download of any file through an “open or save to disk” prompt. module development

  4. This point describes 5 Drupal functions to use when dealing with file download :

    • file_directory_path()
    • variable_get('file_downloads')
    • file_create_url($relativepath)
    • file_create_path($relativepath)
    • theme_image() should be called through the rooter function theme()

    The section explains when to use these functions and what to expect from them. It also provides sample code. file path

  5. This section explains how to use private download — and why we should use the ../privateFolder notation when specifying our File System Path. File System Path for private download

  6. Challenge : we need to change when and how the attachment table is displayed. The solution : we use the themeable function theme_upload_attachments($files) to print the table in node.tpl.php — hence printing the value returned by theme('upload_attachments', $files)or we override that function in template.php. This section provides sample code, and it reminds us of the difference between the variables $teaser and $node->teaser in the template file node.tpl.php : $teaser is a boolean, TRUE if we are to display the teaser as content, while $node->teaser is the content of that teaser. attachment table

  7. What we should know about uploading two files with the same name when using the Drupal core upload module. filename versus filepath

  8. This section explains what hot linking is, and presents 3 different methods to try and prevent it. However, I only recommend the first method, and explain why the others are flawed (these others use the value $_SERVER['HTTP-REFERER']). leaching

  9. The problem : when clean URLs is enabled, we cannot use relative paths to files and images in our html markup. This problem has been discussed on There are at least 4 solutions to this problem :

    • Use an absolute path, possibly resorting to a subdomain or a virtual host.
    • Use the contributed filter module pathfilter, which has been ported to Drupal 6.
    • Set the input format to php and use the function base_path().
    • Set the input format to php and use the function file_create_url() — when the file we want to link to is inside the File System Path.
    relative versus abolute path with clean URLs

  10. This section provides a recipe to scan directories for particular files using the Drupal function file_scan_directory. It provides sample code on how to pick a random image from a folder and all its subfolders. scanning the file system path folder