Submitted by Seb on 20/10/2011 - 18:50
New quick post to share a feature.
To force to download a file, as usual with Drupal, there's a module for that. In this case there are even two: Download file and File force. But you may be reticent to install a module for such a basic feature! So here is the solution in a few lines of code:
Here is a snippet based on File API. It is more secure than the second one but it will not work on files not handled by Drupal (whatever file download method you're using) : thus I recommend it.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| <?php
/**
* Implementation of hook_menu()
*/
function mymodule_menu() {
$items['download/%file'] = array(
'page callback' => 'mymodule_download_file',
'access arguments' => array('administer site configuration'),
'type' => MENU_CALLBACK,
);
return $items;
}
/**
* Page callback for forcing a file to download
*/
function mymodule_download_file($file) {
if($file) {
file_transfer($file->uri, array('Content-disposition' => 'attachment; filename='.$file->filename));
}
else {
return drupal_access_denied();
}
} |
You can download the file with a link like http://mysite.com/download/123 where 123 is the file id (fid) of the file being downloaded.
This second snippet may present a security issue! It is recommended to use it as a last resort when files are not handled by Drupal. To increase security, this feature will be restricted to administrators, and filtered on file extensions.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
| <?php
/**
* Implementation of hook_menu()
*/
function mymodule_menu() {
$items['download'] = array(
'page callback' => 'mymodule_download_file',
'access arguments' => array('administer site configuration'),
'type' => MENU_CALLBACK,
);
return $items;
}
/**
* Page callback for forcing a file to download
*/
function mymodule_download_file() {
if (!isset($_GET['file']) || !file_exists($_GET['file'])) {
return drupal_not_found();
}
$filepath = $_GET['file'];
$realpath = realpath($path);
$filename = basename($filepath);
$extension = pathinfo($filepath, PATHINFO_EXTENSION);
// Check extension and restrict to files in DRUPAL_ROOT
if(in_array($extension, array('jpg', 'png', 'gif', 'mp4')) && substr($path, 0, strlen(DRUPAL_ROOT)) === DRUPAL_ROOT) {
drupal_add_http_header('Content-disposition', 'attachment; filename=' . $filename);
readfile($filepath);
}
else {
return drupal_access_denied();
}
} |
Then you can create your file link as in http://mysite.com/download?file=sites/default/files/myimage.png
It's only working for the public file system handling but it is the most famous one.