hook_file_download

Filefield widget says "Access Denied" on legacy nodes

One of the media heavy sites managed by us, there is a media content type which has been around for a while (starting from Drupal 5). The images associated with the content has been managed through multiple APIs before finally being ported to make use of FileField module. As it happens, the older legacy files were distributed all over the place but the newer files where all structured in a single location.

FileField module can be given a path where all file uploads can reside. Now this path happens to be different from all the paths used in the legacy nodes. Most of the use cases this does not cause a problem. But when there is a need to edit nodes that refer to the legacy files, the FileField widget would say "Access Denied" next to the image in the node edit form.

The reason for this behavior is obvious. The file field widget wants to validate the file path to make sure it is accessible before it can display it (this happens only in the node edit mode; works fine in node view mode). Since the legacy files are in a place which the current configuration of the FileField widget does not know about, it fails the validation and hence says "Access Denied".

The validation, as it happens, is done through hook_file_download API, which is passed the filepath. So a simple work around for this problem is to add a hook_file_download() API in one of our custom modules to validate the path and return appropriate headers as shown in the following code:

/**
 * Implementation of hook_file_download().
 */
function legacyfiles_file_download($filepath) {
  // validate legacy paths
  if (file_exists($filepath)) {
    $filesize = filesize($filepath);
    return array(
      'X-Content-Length: ' . $filesize,
    );
  } else {
    return array();
  }
}