简体   繁体   中英

How can I use PHP headers() in WordPress to download files from my custom plugin page?

I am trying to use PHP headers() in WordPress to download files from my plugin page view , but it is not working as this error message is returned for each header line present in my script:

Warning: Cannot modify header information - headers already sent by (output started at D:\\xampp\\wordpress\\wp-includes\\formatting.php:5100) in D:\\xampp\\wordpress\\wp-content\\plugins\\pxw-test\\pxw-test.php on line 33

And so on for each line of present headers(); in my script...

You can have a look at the pxw-test.php file content (the plugin itself) below:

<?php
    /*
        Plugin Name: Test Headers
        Description: Download File Test Plugin for Headers Response errors.
        Version:     1.0
        Author:      Tester
        Text Domain: pxw_test
    */
    // Exit if accessed directly
    if ( ! defined( 'ABSPATH' ) ) {
        exit;
    }

    //Admin Menu
    function pxw_test_menu() {
        // Create custom top-level menu
        add_menu_page(
        'Dashboard',
        'Test Headers',
        'manage_options',
        'pxw_test',
        'pxw_test_dashboard_page',
        null,
        20
        );
    }


    //Function needed to display top-level page as the main page
    function pxw_test_dashboard_page(){
        // Download
        if(isset($_POST['download'])){

            // File to download
            $filename = 'file.txt';

            // HTTP headers for downloads
            header("Pragma: public");
            header("Expires: 0");
            header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
            header("Content-Type: application/force-download");
            header("Content-Type: application/octet-stream");
            header("Content-Type: application/download");
            header("Content-Disposition: attachment; filename=$filename");
            header("Content-Transfer-Encoding: binary");
            header("Content-Length: ".filesize(plugin_dir_path(__FILE__).$filename));

            //You can try the following
            // while (ob_get_level()) {
            // ob_end_clean();
            // }
            // @readfile(plugin_dir_path(__FILE__).$filename);
        }
        else {
        }
?>

        <form action="" method="POST" enctype="multipart/form-data" style="text-align:center;padding: 100px 0;">
            <button type="submit" onclick="this.form.submit();" style="background:red;padding:10px;color:#fff;cursor:pointer;"><b>Download File</b></button>
            <input type="hidden" name="download" />
        </form>

<?php
    } # End of function pxw_test_dashboard_page().

    // Finally display the menu
    add_action('admin_menu', 'pxw_test_menu');
?>

My goal is to download a file and delete the file after download.

Of course I am not looking for:

A function.php solution as I am building a plugin.

But anything short and manageable from my plugin folder is welcomed.

Such as:

  1. PHP

  2. JavaScript

  3. jQuery

  4. HTML5, such as <iframe> , but not the <a download></a> as I will need to make actions such as deleting the file after download and if the file was downloaded or not.

Working Solution

I understand now that while being inside the function, PHP headers are initiated by the function and stopped when the function ends.

function pxw_test_dashboard_page(){

   // You can not use header() here!
   // For example when you include a PHP file here to display your page view,
   // you have to separate you headers function in a external file
   //then display the output in your file view.

}

So the best solution I have found instead of many trouble hacks is to add:

ob_start();

Somewhere at the beginning of the PHP tags and outside your functions.

Here is the full working Code :

Plugin folder: pxw-test

Plugin folder content:

  1. pxw-test.php

  2. file.txt - Just a file with something inside


pxw-test.php

<?php
    /*
        Plugin Name: Test Headers
        Description: Download File Test Plugin for Headers Response errors.
        Version:     1.0
        Author:      Tester
        Text Domain: pxw_test
    */

    // Exit if accessed directly
    if ( ! defined( 'ABSPATH' ) ){
        exit;
    }

    // Fix PHP headers
    ob_start();

    // Set DB version
    //global $pxw_test_db_version;
    $pxw_test_db_version = '1.0';

    // Admin menu
    function pxw_test_menu() {
        //create custom top-level menu
        add_menu_page(
        'Dashboard',
        'Test Headers',
        'manage_options',
        'pxw_test',
        'pxw_test_dashboard_page',
        null,
        20
        );
    }

    // Function needed to display top-level page as the main page
    function pxw_test_dashboard_page() {

        $target_dir = plugin_dir_path( __FILE__);

        // Download
        if(isset($_POST['download'])){

            // File To Download
            $filename = 'file.txt';

            // HTTP headers for downloads
            header("Pragma: public");
            header("Expires: 0");
            header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
            header("Content-Type: application/octet-stream");
            header("Content-Disposition: attachment; filename=$filename");
            header("Content-Transfer-Encoding: binary");
            header("Content-Length: ".filesize($target_dir.$filename));
            while (ob_get_level()) {
                ob_end_clean();
                @readfile($target_dir.$filename);
            }

            // Do something else after download like delete file
            unlink($target_dir.$filename);
        }
        else{
        }
?>

<form action="" method="POST" enctype="multipart/form-data" style="text-align:center;padding: 100px 0;">
    <button  type="submit" onclick="this.form.submit();" style="background:red;padding:10px;color:#fff;cursor:pointer;"><b>Download File</b></button>
    <input type="hidden" name="download" />
</form>

<?php
    } # End of function pxw_test_dashboard_page()

    // Finally display the menu
    add_action('admin_menu', 'pxw_test_menu');
?>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM