Drupal version: 7.14

Currently drupal save the downloaded filename as the last part of the URL, just like a file link "http://example.com/system/files/abc.txt", the default saved filename is "abc.txt".

I want to ask is how to change "abc.txt" to other filename such as "xyz.txt" while downloading.

  • 2
    Problem has been solved by setting download method to 'private', if it's set to 'public', you cannot do any control over the download process(that is hook_file_download cannot be called under this mode). – Justin May 8 '12 at 8:28
  • 1
    I looked into the function code and I think it'd be great if you could answer your own question and share your code to let others see what could be done by that hook. I bet you could earn some points too :) – Artur May 8 '12 at 9:49

For this issue there's a prerequisite,that is, your download method must be 'private', otherwise there's no chance for drupal to call your 'hook_file_download', it's important!

Here's an example from drupal's file module, change $file->filename to what you want, then return to HTTP headers.

/** * Implements hook_file_download().
* This function takes an extra parameter $field_type so that it may
* be re-used by other File-like modules, such as Image.

function file_file_download($uri, $field_type = 'file') {
global $user;
// Get the file record based on the URI. If not in the database just return.
$files = file_load_multiple(array(), array('uri' => $uri));
if (count($files)) {
foreach ($files as $item) {
// Since some database servers sometimes use a case-insensitive comparison
// by default, double check that the filename is an exact match.
if ($item->uri === $uri) {
$file = $item;
if (!isset($file)) {

//...........................other codes.........................

// Access specifically denied.
if ($denied) {
return -1;

// Access is granted.
$headers = file_get_content_headers($file);
return $headers;


For Drupal 7, when implementing Justin's solution, my download name was still the original filename, not the custom name I assigned to $file->filename. At the time of this writing Drupal 7's file_get_content_headers() sets

$name = mime_header_encode($file->filename);

but never uses the variable $name.

I found a few patches, but instead of patching core, I did the following:

$headers = file_get_content_headers($file);
$headers['Content-Disposition'] = 'attachment; filename="'. $file->filename .'"';
return $headers;

For my purposes, I needed the file to be downloaded, which is why I used 'attachment'. But if you need the disposition to be 'inline', then the following snippet could get you started (copied from this patch):

$inline_types = variable_get('file_inline_types', array('^text/', '^image/', 'flash$'));
$disposition = 'attachment';
foreach ($inline_types as $inline_type) {
  // Exclamation marks are used as delimiters to avoid escaping slashes.
  if (preg_match('!' . $inline_type . '!', $file->filemime)) {
    $disposition = 'inline';

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.