I want to create file programmatically ,I want only authenticated user can download it and direct access return 403 to them. I search and saw How Can I Make File Downloads Available Only to Authenticated Users? but my files not field files(not record in file table) and programmatically I created them with:

          drupal_set_message(t('Problem in write file in directory'),'error');
    //    $filepath='sites\\defauls\\files\\Export-giftcard-.csv';
        $df = fopen($filepath, 'w');
            drupal_set_message(t('Can not write file in').$filepath,'error');
    $path = file_create_url($filepath);
    drupal_set_message(t('Export done. ') . '<a href="' . $path . '">' . t('Download export file') . '</a>');

after rooby answer I update my question

I set private file system to system/files/export and in my code use it $temp1 = variable_get('file_private_path'); also I implement hook_file_download

function mymodule_file_download($uri) {
  // Check if the file is controlled by the current module.
  if (!file_prepare_directory($uri)) {
    $uri = FALSE;
// I will put my conditions later
      $info = image_get_info($uri);
      return array('Content-Type' => $info['mime_type']);

but when I try to click on link to download file return Forbidden to me.I think mymodule_file_download not run when I try to access system/files/export/myfile.csv

  • If you don't want to use file management provided by Drupal, with it's private file system, then it is not really a Drupal question.
    – Mołot
    Feb 24, 2014 at 13:23
  • @Mołot , Is it right if I I create it in private file system direct access to it return 403?
    – Yuseferi
    Feb 24, 2014 at 13:24
  • I honestly don't understand the comment above.
    – Mołot
    Feb 24, 2014 at 13:42
  • I said If I create a file in private file system ,is it accessible directly?
    – Yuseferi
    Feb 24, 2014 at 13:52
  • @Mołot I create file in private file system programmatically, but when I want download it ,it return me 403,Forbidden .
    – Yuseferi
    Feb 24, 2014 at 13:55

2 Answers 2


You can use the private file system instead of the public file system. The private file system restricts direct access to files.

Then you link to the files like: system/files/filename.ext. Then when someone clicks one of those links it calls drupal core's file_download() function, which in turn invokes hook_file_download().

Drupal core implements hook_file_download() in the file module as file_file_download(), which handles these private files to allow users with the appropriate access permissions to download the file.

However file_file_download() won't work out of the box with non drupal field files (like your custom files appear to be), it only works for files attached to drupal fields.

So you will also have to implement your own version of hook_file_download() to handle your particular files.

One way to single out your files and avoid massing with the files that file_file_download() already handles is to put your custom files in a sub-directory of the private files directory that is not used by any other files, then in your hook_file_download() you check for that directory in the file path, return headers if the file is in the right directory and the user has the correct permissions, otherwise, if the user doesn't have perms return -1 and if the file is outside of your special sub-directory just return null to ignore the file and let drupal handle it as normal.

To implement hook_file_download() you have to create a custom drupal module that implements the hook like so:

 * Implements hook_file_download().
function YOURMODULENAME_file_download($uri, $field_type = 'file') {
  // Your code goes here.

See file_file_download() as an example.

For more information see:

Your private file system path will be something like sites/default/files/private (a directory on your server). The path system/files is a drupal website url, not a path on the file system, and is only used to create hyperlinks to the files that are in the private files directory.

So if you set your private file system path to sites/default/files/private, a hyperlink on your site that points to /system/files/export/filename.txt will open the file on your web server at /sites/default/files/export/filename.txt.

  • I understand your theory,but how can I implement it in form sumbmit, I want download file after form submit,
    – Yuseferi
    Feb 24, 2014 at 14:26
  • you mean I implement hook_file_download and in sumbit of my form do something like this ? insumbit{ return mymodule_file_download($path); } ?
    – Yuseferi
    Feb 24, 2014 at 14:29
  • The hook_file_download() handles your access control to your custom file. The download code can be just like you already have except you are saving the file to the private file system instead of the public one and the link to the file that you are creating links to /system/files/filepath.ext instead of /sites/default/files/private/filepath.ext
    – rooby
    Feb 24, 2014 at 14:29
  • When a user downloads a file from system/files/... drupal proccesses it as a private file and then runs hook_file_download() to determine the access control for the file instead of just directly serving the file as it would for a public file.
    – rooby
    Feb 24, 2014 at 14:30
  • I dont understand how can this hook engaged to run? should I call it in my form_submit?
    – Yuseferi
    Feb 24, 2014 at 14:30

Create a private file field as you would if they were regular private files.

Hook in to the file download function: https://api.drupal.org/api/drupal/modules%21system%21system.api.php/function/hook_file_download/7

Let Drupal handle permissions, create your file dynamically.

  • @zhilevan that error suggests that you need to learn how to properly hook in to drupal functions... and is beyond the scope of this question (and this forum). Read the documentation at drupal.org, it will tell you how to properly hook.
    – jdu
    Feb 24, 2014 at 14:32

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.