2

I had this issue before, and last time the problem was that node was unpublished. The private file became accessible when the node was published.

This time, however, I'm not using a node. I'm just using Drupals file manage system to store my own files for my own custom module. SO I generated a url for an image file like so:

$imageFile = file_load($userInput['fid']);
$style = \Drupal::entityTypeManager()->getStorage('image_style')->load('thumbnail');
$url = $style->buildUrl($imageFile->getFileUri());

If I print out the URL, I get:

http://localhost/system/files/styles/thumbnail/private/cfiles/test.png?itok=Le14o4Zs

But when I access that, i get "access denied".

What am I missing?

3 Answers 3

7

In Drupal 8, private file permissions by default are given according to the entity to which they are attached. If the user has permission to view the entity, they will have permission to view the file.

If you are not attaching the file to an entity, then you will need to implement hook_file_download(), where you will determine whether or not the user has permission to access the file, and return a value accordingly. Currently, because you have no implemented this, access is denied by default.

Note that this hook can be implemented even when the file is attached to an entity to provide additional access checks and/or additional headers.

2

Another nice way to negotiate file access according some more complex conditions than hook_file_download($uri) allows you to check for, is to implement hook_ENTITY_TYPE_access for the file entity and check if the $operation equals 'download' like in the snippet below. There you also have access to the actual $file entity.

use Drupal\Core\Access\AccessResult;
use Drupal\Core\Session\AccountInterface;
use Drupal\file\FileInterface;

/**
 * Implements hook_ENTITY_TYPE_access().
 */
function MYMODULE_file_access(FileInterface $file, $operation, AccountInterface $account) {
  if ($operation === 'download') {
    // Do access stuff ...
    // ...
    // ...
  }
  // No opinion.
  return AccessResult::neutral();
}
2

Like Jaypan said, If you are not attaching the file to an entity, then you will need to implement hook_file_download(), where you will determine whether or not the user has permission to access the file.

Here is a code example that can help :

/**
 * Implements hook_file_download().
 */
function mymodule_file_download($uri) {
  // Check if the file is private.
  if (StreamWrapperManager::getScheme($uri) == 'private') {

    // Exclude file not in location.
    if (strpos($uri, '/location/') === false) {
      return NULL;
    }

    $account = Drupal::currentUser();
    $user_roles = $account->getRoles();

    // Check if user has the authorized role.
    if (in_array('administrator', $user_roles)
      || in_array('country_administrator', $user_roles)
      || in_array('super_administrator', $user_roles)) {
      return ['Content-disposition' => 'attachment'];
    }
  }

  return NULL;
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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