I am puzzled how to alter the response headers from specific hook (hook_file_download)?

 * Implements hook_file_download().
function example_file_download($uri) {
  $scheme = FileSystem::uriScheme($uri);
  if ($scheme === 'public') {
// Set custom headers here.


Basically I want under certain conditions to set additional headers and in D7 this would happen with drupal_add_http_header() but in D8 as far as I can see this can happen only by implementing custom subscriber and using getSubscribedEvents and then KernelEvents. However this does not solve my case as I want to add custom headers only for specific file types.

If I use custom subscriber then this would be possible by:

* {@inheritdoc}
public static function getSubscribedEvents() {
$events[KernelEvents::RESPONSE][] = ['exampleFunc'];

return $events;

And then:

public function exampleFunc(FilterResponseEvent $event) {

$response->headers->set('Header', 'Value');

in D7 this would happen with drupal_add_http_header()

In other hooks that might have been true, but hook_file_download works the same in Drupal 8 as it did in Drupal 7, without using drupal_add_http_header.

This is the documentation for both versions’ return value from that hook:

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.

Emphasis mine.

You can't get access to the response object in hook_file_download, because it doesn't exist yet. It's not created until after the hook is invoked in FileDownloadController::download(). The headers you return are added to the response, so returning a suitable key-value array from the hook is the way to achieve what you want.

  • Hi, thanks for the answer but the problem is not with hook_file_download itself. Basically what Im trying to do is to add $response->headers->set('HEADER', 'value'); from hook_file_download() but I cant figure out how to use the response object from there. – tslid Apr 5 '19 at 18:59
  • The response doesn't exist at that point - it's created after the invocation. See FileDownloadController::download(). The key-value array of headers you return from hook_file_download are added to the response, so it's essentially the same op – Clive Apr 5 '19 at 19:37
  • I can't believe how I missed this even when you bolded it in the answer... Thank you very much, let me know where I can send you a beer! – tslid Apr 5 '19 at 19:57
  • You're welcome, and don't worry about the beer - I've already had waaaay too much guinness tonight, let's just pretend you bought me one of those ;) – Clive Apr 5 '19 at 20:05

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.