Hi,
for a module that I'm developping, I need to send files that are in formats other than HTML (images, PDFs ...).
These files are either found or generated dynamically by my module (they are not accessible by direct URL nor node attachements).
I have a callback function corresponding to a page in my module's menu, that determine which file has to be sent, then sends it.
In PHP, it looks like :


function mymodule_mycallbackfunction() {
    $pathToFile = '/a/file/some/where.pdf';
    header('Content-type: '.mime_content_type($pathToFile));
    print(file_get_contents($pathToFile));
    exit();
}

It works fine, but the problem is that code is "dirty" :

1st) my callback function is supposed to return some HTML, but what I do here is not returning anything, moreover I stop the execution with "exit()" in order to avoid Drupal adding some HTML for menus and blocks ...

2nd) when I do that, no cacheing is done. But for performance I really need drupal to place the files contents and content-type headers in cache, and I want to let Drupal do it "normally".

I guess there must be a better way to do it, but I ignore it ...
Is there a dedicated function ? a hook to implement ? a module that would give me the good API ? ...

Thanks,

Hervé

Comments

coofercat’s picture

I've often wondered this too. For many situations, calling exit() is fine because you do actually want to short-circuit Drupal's exit hooks and the like.

However, I'm not sure there's a nice way to get out of Drupal without spitting out a whole load of HTML. In my application, I'm trying to output XML or JSON, but I'd still like to give modules a chance to run their exit hooks (especially modules like statistics).

I'm not sure there's any way to tell Drupal you don't want HTML content. Certainly, there doesn't seem to be a way to specify (or check) what content type is being composed, so I'm guessing this isn't possible. I guess we have to wait for D7/D8 or something.

Meantime, I can only suggest calling any modules you want, and then just call exit() as you need. You'll probably want to stick all that stuff in a function, eg. mymodule_custom_exit(). Be careful not to call your exit function mymodule_exit(), because that will make it into an exit hook, called by other modules(!).

coofercat’s picture

Actually, one way does seem to be in use... that is to use a theme template. Take a look at the views_datasource module for an example.