1

in my functions.php file I've added a custom action for the template_redirect hook which must force download a file stored on the server. The code of the download works fine when it is in a simple PHP file outside of Wordpress. But the feature is broken as soon as I add this code inside my template _redirect hook. Chrome says "The site cannot be reached ... ERR_INVALID_RESPONSE". There is no error 500 or other error...

Here's the download code :

<?php
$filename = $_SERVER['DOCUMENT_ROOT'] . 'path-to-my-wordpress/wp-content/uploads/export/test.html';
header( "Expires: 0" );
header( "Cache-Control: no-cache, no-store, must-revalidate" );
header( 'Cache-Control: pre-check=0, post-check=0, max-age=0', false );
header( "Pragma: no-cache" );
header( "Content-type: text/html" );
header( "Content-Disposition:attachment; filename=\"" . basename( $filename ) . "\"" );
header( "Content-Type: application/force-download" );
readfile( "{$filename}" );
?>

Here's the template_redirect hook :

add_action( 'template_redirect', 'my_template_redirect' );
function my_template_redirect() {
$filename = $_SERVER['DOCUMENT_ROOT'] . 'path-to-my-wordpress/wp-content/uploads/export/test.html';
header( "Expires: 0" );
header( "Cache-Control: no-cache, no-store, must-revalidate" );
header( 'Cache-Control: pre-check=0, post-check=0, max-age=0', false );
header( "Pragma: no-cache" );
header( "Content-type: text/html" );
header( "Content-Disposition:attachment; filename=\"" . basename( $filename ) . "\"" );
header( "Content-Type: application/force-download" );
readfile( "{$filename}" );
exit();
}

Any idea ?

EDIT

After some more tests, the problem seems to come from the specific URL from which I'm trying to run this download. In fact, my code is like this :

add_action( 'template_redirect', 'my_template_redirect' );
function my_template_redirect() {
    if ( preg_match( "/\/wp-admin\/export$/", $_SERVER['REQUEST_URI'] ) ) {
        $filename = $_SERVER['DOCUMENT_ROOT'] . 'path-to-my-wordpress/wp-content/uploads/export/test.html';
        header( "Expires: 0" );
        header( "Cache-Control: no-cache, no-store, must-revalidate" );
        header( 'Cache-Control: pre-check=0, post-check=0, max-age=0', false );
        header( "Pragma: no-cache" );
        header( "Content-type: text/html" );
        header( "Content-Disposition:attachment; filename=\"" . basename( $filename ) . "\"" );
        header( "Content-Type: application/force-download" );
        readfile( "{$filename}" );
        exit();
    }
}

The URL is /wp-admin/export and this should launch the download of the file. Without this URL condition, the code does work when I reach the base site URL (= http://mysite.dev/). But with the condition adn trying to reach http://mysite.dev/wp-admin/export, it breaks. I also tried without the wp-admin prefix, and it also breaks.

15
  • you definitely need to exit to halt execution after the file is output.
    – Milo
    Commented May 12, 2017 at 16:16
  • I forgot the exit(); in my example, but I do have it in my code. And it doesn't work. Commented May 12, 2017 at 16:57
  • works fine for me in latest WordPress, no plugins, twentysixteen theme.
    – Milo
    Commented May 12, 2017 at 18:12
  • also note that technically, you can't have two different Content-type headers, but that shouldn't break anything.
    – Milo
    Commented May 12, 2017 at 18:12
  • This seems to come from my custom theme... Commented May 12, 2017 at 19:22

3 Answers 3

2

The solution is in fact very simple. Just use the action admin_post_(action)...

add_action( 'admin_post_export_page', 'export_page' );
function export_page() {
    // any code you want
}

than you can make custom links admin_url( 'admin-post.php?action=export_page&id=' . $post->ID );

Thanks Milo for giving the solution.

0

Error 500 This is a server error, so I assume it is related to or read of the file or its delivery to the client.

The problems I currently see as possible that cause the problem are: 1) You have twice submitted the content type but different settings and parallels. 2) The second time you send an application / force-download type, there are servers that are problematic for them if they do not know the mime type that is being sent.

Try the following code:

add_action( 'template_redirect', 'my_template_redirect' );
function my_template_redirect() {
    if ( strpos( $_SERVER['REQUEST_URI'], admin_url( 'export' ) ) !== false ) {
        $upload_dir = wp_upload_dir();
        $filename = $upload_dir['basedir'] . '/export/test.html';

        header( "Expires: 0" );
        header( "cache-Control: no-cache, no-store, must-revalidate" );
        header( "Pragma: no-cache" );
        header( "content-disposition: attachment; filename=" . basename( $filename ) );
        header( "content-type: application/octet-stream" );
        header( "content-length: " . filesize( $file ) );
        readfile( $filename );
        die();
    }
}
-1

Your not adding your redirect page

 add_action( 'template_redirect', 'my_template_redirect' );
    function my_template_redirect() {
    $filename = $_SERVER['DOCUMENT_ROOT'] . 'path-to-my-wordpress/wp-content/uploads/export/test.html';
    header( "Expires: 0" );
    header( "Cache-Control: no-cache, no-store, must-revalidate" );
    header( 'Cache-Control: pre-check=0, post-check=0, max-age=0', false );
    header( "Pragma: no-cache" );
    header( "Content-type: text/html" );
    header( "Content-Disposition:attachment; filename=\"" . basename( $filename ) . "\"" );
    header( "Content-Type: application/force-download" );
    readfile( "{$filename}" );
    // Add your redirect page here
    wp_redirect( home_url( '/pagename/' ) ); /// works on my install sends to new page
    exit();
    }
6
  • This doesn't work on my install :-( I 'm testing on a fresh install of Wordpress without any plugins. I'm on a Mac with MAMP and PHP 7.0.13. Commented May 12, 2017 at 17:52
  • Did it redirect you? what errors are you getting?
    – Sam
    Commented May 12, 2017 at 18:09
  • no redirection, same error as previous test Commented May 12, 2017 at 18:12
  • maybe the template_redirect hook is not the right thing to use for this purpose... but what else ? Commented May 12, 2017 at 18:13
  • I edited my post with more tests... Commented May 12, 2017 at 19:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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