Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I want to serve a dynamically-generated PDF with a "File Transfer" header

header('Content-Description: File Transfer');

However, before I generate the document I need to verify the user's login and credentials.

if(is_user_logged_in()){
     $currentUser = wp_get_current_user();
     $userLogin = $currentUser->user_login;
     if(userAllowedAccess($requestID, $userLogin)){
         header('Content-Description: File Transfer') 
         ....... file content
     }
     else{
         //Do nothing... get off my lawn
     }

}

Where do I put this so I don't get any headers or output from my wordpress page? I need to load enough of the API to get my is_user_logged_in() and wp_get_current_user() function but don't want to load anything that prints to the page...

Suggestions?

Thanks- J

share|improve this question
add comment

2 Answers

I think you mean the Content-Disposition header.

I recently did a very similar thing for a client. My weapon of choice: custom rewrite rules.

First, add the rewrite:

<?php
add_action( 'init', 'wpse27232_add_rewrite' );
/**
 * Adds the rewrite rule for the download.
 * 
 * @uses add_rewrite_rule
 */
function wpse27232_add_rewrite()
{
    add_rewrite_rule(
        '^download/?$',
        'index.php?file_download=true',
        'top'
    );
}

When someone visits yoursite.com/download they will catch this rewrite. Notice the index.php?file_download=true bit. WordPress has no clue that file_download should be a recognized query variable. So let's make that recognizable by filtering query_vars.

<?php
add_filter( 'query_vars', 'wpse27232_query_vars' );
/**
 * Filter our query vars so WordPress recognizes 'file_download'
 */
function wpse27232_query_vars( $vars )
{
    $vars[] = 'file_download';
    return $vars;
}

Now the fun part: catch the file_download query variable and send the file.

<?php
add_action( 'template_redirect', 'wpse27232_catch_file_dl' );
/**
 * Catches when the file_download query variable is present.  Sends the content
 * header, the file, and then exits.
 */
function wpse27232_catch_file_dl()
{
    // No query var?  bail.
    if( ! get_query_var( 'file_download' ) ) return;

    // change this, obviously. Should be a path to the pdf file
    // I wrote this as a plugin, hence `plugin_dir_path`
    $f = plugin_dir_path( __FILE__ ) . 'your-file.pdf';
    if( file_exists( $f ) && is_user_logged_in() )
    {
        // Do your additional checks and setup here

        // Send the headers
        header('Content-Type: application/pdf');
        header('Content-Disposition: attachment; filename=' . basename( $f ) );
        header( 'Content-Length: ' . filesize($f));
        // You may want to make sure the content buffer is clear here

        // read the pdf output
        readfile($f);
        exit();
    }
    else
    {
        global $wp_query;
        $wp_query->is_404 = true;
    }
}

Finally to get this little plugin to work, an activation hook to flush the rewrite rules.

<?php
register_activation_hook( __FILE__, 'wpse27232_activation' );
function wpse27232_activation()
{
    wpse27232_add_rewrite();
    flush_rewrite_rules();
}
share|improve this answer
add comment

There are multiple approaches to do such:

  • page template
  • Ajax action
  • custom handler that loads core
  • early hook (such as template_redirect)
  • and so on...

Personally I'd go with Ajax action. It's pretty clean way to get full environment without any output and not overly complex to implement. See AJAX in Plugins in Codex.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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