Reputation: 13267
I'm trying to show a HTML page with PHP right before it downloads a file. I understand that I can't redirect to a different page and download a file at the same time, but why wouldn't this work?
echo "<html>...Example web page...</html>";
$download = '../example.zip'; //this is a protected file
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename=example.zip');
readfile($download);
The file downloads, but it never shows the HTML page that is echoed. But if I remove the download, the page shows.
Upvotes: 0
Views: 362
Reputation:
Because you cannot output anything before pushing custom headers out, I would suggest using JS to redirect to the download, which usually keeps you on the same page (as long as you're just disposing the zip content and nothing else).
So, try this:
$download = 'example.zip';
echo '<head> <script type="text/javascript"> function doRedirect(){window.location = "'.$download.'"}</script>
</head><html><script type="text/javascript"> doRedirect() </script> <...Example web page...</html>';
Or if you need a timer on it:
echo '<head> <script type="text/javascript"> function doRedirect(){window.location = "'.$download.'"}</script>
</head><html><script type="text/javascript">
setTimeout(doRedirect,1000);//wait one second</script> <...Example web page...</html>';
EDIT:
If you want to hide the file path, I would suggest making a download script, which JS will redirect to.
So basically, do exactly what you're doing, then use JS to point to it. Like this:
Download.php:
//use an ID or something that links to the file and get it using the GET method (url params)
$downloadID = $_GET['id'];
//work out the download path from the ID here and put it in $download
if ( $downloadID === 662 )
{
$download = 'example.zip';//...
}
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename=$download');
readfile($download);
And then in your main HTML file, use JS to point to it, with the correct ID:
<head> <script type="text/javascript"> function doRedirect(){window.location = "Download.php?id=662"}</script>
</head><html><script type="text/javascript"> doRedirect() </script> <...Example web page...</html>
Upvotes: 0
Reputation: 7351
As has already been said, you cannot send headers after output is already sent.
So, this may work for you:
header('Refresh: 5;URL="http://example.com/download.php"');
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename=example.zip');
readfile($download);
http-equiv
in <meta http-equiv="refresh"
means the name
and value
is equivalent to an HTTP header, so it does the same thing the Refresh:
header.
Download any file from SourceForge, and you will see a JavaScript implementation (Your download will start in 5 seconds...
).
Upvotes: 0
Reputation: 17624
You can't set header information after content is sent to the browser. If you're actually getting the download - there's likely some output caching going on someplace.
For what you're trying to accomplish, you may want to show the HTML content, and use a <meta>
tag or JavaScript to redirect to the download script. I believe most browsers will start the download while keeping the last loaded page visible to the user (which should be essentially what you want to do).
<meta http-equiv="refresh" content="1;URL='http://example.com/download.php'">
Or:
<script type="text/javascript">
window.location = "http://example.com/download.php"
</script>
Upvotes: 1
Reputation: 160883
There is a simple principle:
Remember that header() must be called before any actual output is sent, either by normal HTML tags, blank lines in a file, or from PHP.
The solution is to prepare two page, one for show the html content, one for download.
In page 1, using javascript to set a timer to redirect to the download link after several time.
For example, "After 5 second, the download will begin.".
Upvotes: 0