Search code examples
phpwordpressexcelpluginsheader

How to correctly make a Wordpress plugin returns a downloadable excel file


I'm trying to make some reports for my wordpress plugin. This reports must be downloadable as excel. Basically what I did was creating a button and when that button were pressed, I will query the database and make an excel from the results.

Now I need to modify the header to return the results as excel file. This is how I did it:

header('Content-Disposition: attachment; filename='.$filename.'.xls');
header('Content-type: application/force-download');
header('Content-Transfer-Encoding: binary');
header('Pragma: public');
print "\xEF\xBB\xBF"; // UTF-8 BOM

The problem is it returns the following error:

Warning: Cannot modify header information - headers already sent by (output started at .....\wp-admin\menu-header.php:137) 

I probably need ob_start() for this, but isn't that ob_start() must be placed BEFORE the first header (which is from the core files of Wordpress). I prefer not to modify the core files if possible.

Or maybe Wordpress' own hook 'send_headers'? but I can't get it to work, it's still generate the same error.

So what do I need to solve this problem? Is there exist another way to grenerate an excel file from wordpress plugin?

Any help appreciated!


Solution

  • You send a header too late since header() is already sent in menu-header.php. From the code provided i can't see at which point you are sending header, but a good place would be in plugins_loaded action since that action hook is called when all plugins have been loaded, and before any output is sent.

    The link for download can look like this:

    <a href="<?php echo admin_url( '?download' ); ?>">download</a>
    

    And, plugins_loaded action:

    add_action( 'plugins_loaded', function() {
        if ( isset( $_GET['download'] ) ) {
            // here you can create .xls file
    
            header('Content-Disposition: attachment; filename='.$filename.'.xls');
            header('Content-type: application/force-download');
            header('Content-Transfer-Encoding: binary');
            header('Pragma: public');
            die();      
        }
    });