I’m trying to make a page where a user provides an ID of a attachment and the site will set the headers and deliver that file instead of a 404 page. so /download/1754 would lookup the attachment with that Id and output it for viewing/download depending on the file type.

I just can’t think of a wordpress friendly way to do this from inside a plugin. I considered using add_rewrite_rule but couldn’t see a good way around it, also considered checking $_SERVER[‘REQUEST_URI’] to deliver the content before any HTML but then I’d have to stop the page from rendering a 404 and I was not sure of a WordPress friendly way to do this.

My current idea was to have my plugin make a download page, assign a template and have that template run the logic instead of my plugin class. while I have used this before for another situation it was very messy as I had to write a lot of code to force users to be unable to update or edit the file and recreate/delete it on activation.deactivation. so ideally I’d like to avoid that.

2 Answers
2

You’re on the right path with a rewrite rule. If you’re just delivering a file, you can hook an early action, check if a download was requested, then output the file and exit before WordPress ever gets to the stage of querying the database and deciding the request is a 404.

// add the download ID query var which we'll set in the rewrite rule
function wpd_query_var( $query_vars ){
    $query_vars[] = 'download_id';
    return $query_vars;
}
add_filter( 'query_vars', 'wpd_query_var' );

// add rewrite rule
function wpd_rewrite(){
    add_rewrite_rule(
        'download/([0-9]+)/?$',
        'index.php?download_id=$matches[1]',
        'top'
    );
}
add_action( 'init', 'wpd_rewrite' );

// check for download_id and output the file
function wpd_request( $wp ){
    if( array_key_exists( 'download_id', $wp->query_vars ) ) {
        // output your headers and file here
        // ID is in $wp->query_vars['download_id']
        // then exit to halt any further execution
        exit;
    }
}
add_action( 'parse_query', 'wpd_request' );

Leave a Reply

Your email address will not be published. Required fields are marked *