1

I have the following scenario:

A Wordpress plugin (shortcode) is showing a form with a "submit" button. When the submit button is pressed, an Excel 2007 file (.xlsx) is generated and sent to the browser for download via HTTP headers. This works perfectly in Chrome and Firefox, but when I try this using the Microsoft Edge browser (v. 40.15063.0.0) or Internet Explorer (v. 11.540), the download is not triggered, instead the browser redirects directly to

http://example.com/wp-admin/admin-ajax.php

and stops.

I suspect it has something to do with the headers sent by the plugin (php). When I changed the content-type header from

Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet

to

Content-Type: application/vnd.ms-excel

it starts a file download, however the file is empty (and had the wrong file name) because the File I generate is Excel 2007 but the latter content type is for an older Excel file version (which I do not want to generate). I also tried both content types with added ;charset=utf-8 with the same result.

Excerpt from my main plugin file:

add_action( 'wp_ajax_myplugin_generate_report', 'handle_report_request' );
add_action( 'wp_ajax_nopriv_myplugin_generate_report', 'handle_report_request' );

function handle_report_request() {

    // Check the nonce
    if ( empty($_POST) || !wp_verify_nonce($_POST['abcd'],'myplugin_generate_report') ) {
        exit; 
    }

    try {
        $date = new DateTime("now");
        $output_filename = "Report_Prefix" . $date->format("Ymd");
        $writeExcel($output_filename);
    } catch (Exception $ex) {
        echo "Error generating report: " . $ex->getMessage();
    } finally {
        wp_die();
    }
}

function writeExcel($outputFilename) {
  $excelObj = new PHPExcel();

  [... populating PHPExcel object ...]

  // Redirect output to a client’s web browser (Excel2007)
  header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', true, 200);
  header('Content-Disposition: attachment;filename="' . $outputFilename . '.xlsx"');
  // header("Content-Type: application/vnd.ms-excel; charset=utf-8");
  header('Cache-Control: max-age=0');
  header ('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); 
  header ('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT'); 
  header ('Cache-Control: cache, must-revalidate'); // HTTP/1.1
  header ('Pragma: public'); // HTTP/1.0

  $objWriter = PHPExcel_IOFactory::createWriter($excelObj, 'Excel2007');
  $objWriter->save('php://output');
}

The HTML/PHP code with the form elements:

<form action="<?php echo admin_url('admin-ajax.php'); ?>" method="post">
    <?php wp_nonce_field('myplugin_generate_report','abcd'); ?>
    <input name="action" value="myplugin_generate_report" type="hidden">
    <input type="submit" value="Generate report">
</form>

I have tried deactivating/changing some headers but to no effect. Edge refuses to generate the file.

joedoe150
  • 103
  • 1
  • 10
  • _“it starts a file download, however the file is empty (and had the wrong file name) because the File I generate is Excel 2007 but the latter content type is for an older Excel file version”_ - as long as you are _saving_ the file (as opposed to trying to open it directly), that should not matter one single bit - the file system does not care about a “content-type” ... And it should not make the file “empty” either - the Content-Type header has no influence on what body data your script actually returns. – CBroe Aug 30 '17 at 11:48
  • If you don’t need to functionality to _open_ this with the right application right from the “Save as ...”, but saving the file to disk only is enough, then I would try a “generic” Content-Type such as `application/octet-stream` instead. (https://stackoverflow.com/q/20508788/1427878) – CBroe Aug 30 '17 at 11:50
  • @CBroe I have just tried 'application/octet-stream' - this results in the same non-download and redirect problem. To your earlier comment: I am not saving the file, I need the file to be opened directly (i.e. generate the download of the file in the browser). I understand that the content type would not matter for saving a file, I need Edge to be able to download this. I think when I set it to vnd.ms-excel but left the $objWriter set to Excel2007, the browser received a stream to download but could not match it up with the specified content-type, hence the "empty" file. – joedoe150 Aug 30 '17 at 11:54
  • Why are you sending this form to `/wp-admin/admin-ajax.php` in the first place? Are you using AJAX to submit this form? You can not trigger a download dialog directly from a background request. And sending non-AJAX requests to this endpoint would not make much sense either. – CBroe Aug 30 '17 at 11:59
  • @CBroe It is my understanding that `/wp-admin/admin-ajax.php/` is one of the main Wordpress URLs to receive form submissions, they do not have to be made via AJAX to work. Again, this code works perfectly in any other browser (including Android browser), just not in Edge or IE. I just changed the logic to use the `/wp-admin/admin-post.php` url and got the same behavior, this time redirecting to `http://example.com/wp-admin/admin-post.php`. – joedoe150 Aug 30 '17 at 12:12
  • I’d try and remove all those caching-related headers ... older IE often had problems with that when it comes to stuff such as “downloading” PDFs the same way. – CBroe Aug 30 '17 at 12:14
  • @CBroe Just tried that - only left the 2 content headers - still no joy – joedoe150 Aug 30 '17 at 12:17

0 Answers0