Tallboy
Tallboy

Reputation: 13417

How do i send headers in php without creating a new file?

I'm using wordpress to create a 'download' popup that goes to a file attachment ID. The complexities aren't important, but basically I have it open in a new window with a "Download" link.

The file type is going to be mp3 so I don't want the browser to go to the mp3 and try to use an embedded quicktime player or anything like that, I just want it to force it to download.

Is there an easier way to do this than using php header() type stuff?

My 'download' popup has a whole bunch of code in it that loads the WP environment, pulls some attachment urls, changes the title of the page, etc, so its not like the php file can be blank with no whitespace except JUST the header() code (which I know it cant have anything else in the file in order to work).

Here's the code for the popup window that comes up with the 'download' link. to sum up my question, how do i make the download link in the following code just download the mp3 rather than trying to load it into the browser.

As a sidenote is there a way i can close the window automatically once the download starts? Its not a big deal because I have a close window that would just be nice.

<?php
/**
 * Front to the WordPress application. This file doesn't do anything, but loads
 * wp-blog-header.php which does and tells WordPress to load the theme.
 *
 * @package WordPress
 */

/**
 * Tells WordPress to load the WordPress theme and output it.
 *
 * @var bool
 */
define('WP_USE_THEMES', false);
require('./wp-blog-header.php');

$mix_id = $_GET['m'];
$track_id = $_GET['t'];

$mix_attachment_id  = get_post_meta( $mix_id, 'zip', true );
$mix_attachment_url = wp_get_attachment_url( $mix_attachment_id );

// Update download count
$downloads = get_post_meta($mix_id, 'downloads', true);
$downloads = (int)$downloads + 1;
update_post_meta($mix_id, 'downloads', $downloads );

// Determine if track or mix download
if ($track_id == '') {
  // Mixtape Play
  $title = get_the_title($mix_id);
  $link_text = "Download Mixtape";
  $download_link = wp_get_attachment_url( $mix_attachment_id );
} else {
  // Track Download
  $title = get_the_title($track_id);
  $track_attachment_id = get_post_meta($track_id, 'mp3', true);
  $download_link = wp_get_attachment_url( $track_attachment_id );
  $link_text = "Download Track";

}
?>
<!DOCTYPE html>
<html>
<head>
<title><?php echo $title; ?></title>
<style type="text/css">

  body {
    text-align: center;
    margin-top: 40px;
    font-family: arial, sans-serif;

  }

  a.download {
    background: #1B62A0;
    font-size: 28px;
    padding: 10px 20px;
    color: #fff;
    -webkit-border-radius: 10px;
    -moz-border-radius: 10px;
    border-radius: 10px;
    text-decoration: none;
    display: inline;
  }

  a.download:hover {
    background: #5DD8F0;
  }

  a.close {
    text-align: center;
    margin-top: 20px;
    display: block;
  }
</style>
</head>
<body>
  <a class="download" href="<?php echo $download_link; ?>"><?php echo $link_text; ?></a>
  <a href="#" class="close" onclick="javascript:window.close(); return false;">Close Window</a>
</body>
</html>

Upvotes: 1

Views: 280

Answers (3)

Mr Wednesday
Mr Wednesday

Reputation: 552

I've done something similar, although not within WP. I don't understand why you can't just do the Header() logic at the top of the page, before any headers are sent?

Something like below should work, just put it at the top of the page

$s_filename = $_GET['s'];

// SAVE FILE
if( !empty( $s_filename ) )
{
    if( file_exists( $s_filename ) ) 
    {
            $fsize = filesize( $s_filename );
            // SET HEADERS
            header("Content-Disposition: attachment; filename = " . $s_filename);
            header("Content-Type: application/octet-stream");
            header("Content-Length: " . $fsize);
            header("Cache-Control: private");

            readfile( $s_filename );

            $result = "Your file download will begin shortly.<br />\r\n";
    }
}
else
{
    $result = "Error: File not found.<br />\r\n";
}

Upvotes: 1

Cfreak
Cfreak

Reputation: 19309

You either have to use header() or you have to link directly to the file. You could use a single script though by simply adding an if statement. Something like:

// wordpress stuff

if( !empty($_GET['do_download']) ) {  
    // headers here and output the mp3 file.
}
else {
    // show the download page
}

The main thing you have to ensure is that you don't output anything (including blank lines!) before you call header()

Note in my example I accessed $_GET directly. I believe there's a Wordpress specific way to access it and you should use that instead (I just don't know what it is offhand)

Upvotes: 1

Martin Bean
Martin Bean

Reputation: 39389

You need to specify a couple of PHP headers to prompt the user to download the file: http://php.net/manual/en/function.header.php#example-4064.

Basically, the combination of headers and readfile() with an exit after tells the browser to offer the file as a download as opposed to displaying it as a web page.

Upvotes: 2

Related Questions