| 5 core.php | hook_file_download( |
| 6 core.php | hook_file_download( |
| 7 system.api.php | hook_file_download($uri) |
| 8 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.
Parameters
$filepath: String of the file's path.
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.
Related topics
File
- developer/
hooks/ core.php, line 528 - These are the hooks that are invoked by the Drupal core.
Code
<?php
function hook_file_download($filepath) {
if ($filemime = db_result(db_query("SELECT filemime FROM {fileupload} WHERE filepath = '%s'", file_create_path($filepath)))) {
if (user_access('access content')) {
return array('Content-type:' . $filemime);
}
else {
return -1;
}
}
}
?> Login or register to post comments
Comments
Dont get it
When does this hook is executed?, if i do call the file_tranfer function or when i just click a link to the path of the file (i reallly dont think this last one be the one).
This half way to finding out
A grep finds where the hook is called
$ egrep -nR "'file_download'" *includes/file.inc:886: $headers = module_invoke_all('file_download', $filepath);
modules/system/system.module:202: 'page callback' => 'file_download',
{imagefield}
{ Some UberCart modules }
{ImgCache}
The file.inc:886 case is interesting where the hook is run
<?php
/**
* Call modules that implement hook_file_download() to find out if a file is
* accessible and what headers it should be transferred with. If a module
* returns -1 drupal_access_denied() will be returned. If one or more modules
* returned headers the download will start with the returned headers. If no
* modules respond drupal_not_found() will be returned.
*/
function file_download() {
// Merge remainder of arguments from GET['q'], into relative file path.
$args = func_get_args();
$filepath = implode('/', $args);
// Maintain compatibility with old ?file=paths saved in node bodies.
if (isset($_GET['file'])) {
$filepath = $_GET['file'];
}
if (file_exists(file_create_path($filepath))) {
$headers = module_invoke_all('file_download', $filepath);
if (in_array(-1, $headers)) {
return drupal_access_denied();
}
if (count($headers)) {
file_transfer($filepath, $headers);
}
}
return drupal_not_found();
}
?>
The system.module:202 result shows a menu item where the function is described as a page handler:
<?php$items['system/files'] = array(
'title' => 'File download',
'page callback' => 'file_download',
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
?>
So, putting these two thing together: the file_download function implements the hook when handling downloading an existing file on the system, which the system module provides the path for.
Note that some of the modules were using the hook to test permissions on a file, bypassing the file.inc:file_download() function.
There is likely more, but this is a good start.
One more question
Hi, I just saw your tip here and I would have another question:
1. This creates the url for my page_callback$items['mymodule/licenses'] = array(
'title' => 'File download',
'page callback' => 'file_download',
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
2. But what does follow now? I guess I need to implement the hook 'file_download' but what exactly does the hook do for me?
I am trying to set up a url for my module where a user can download a license file which got generated for him.... Could you please help?
Thanks, Uwe