3

Is it possible to redirect a page after a readfile()?

I tried to use Header, but that doesn't work. Also the meta redirect doesn't work either:

header ("Content-Type: application/pdf");

header("Content-Disposition: attachment; filename=$file");
header("Content-Length: $size");

readfile($file_path);  // Giving file to the customer
// header('Location:../checkout.php');  Doesn't work
// echo ('<meta http-equiv="refresh" content="1;url=../checkout.php">');  Doesn't work
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
akano1
  • 40,596
  • 19
  • 54
  • 67
  • 1
    Can you post some sample code, because you could be using header in the incorrect way? Thanks! – Buggabill Nov 29 '10 at 13:26
  • What are you doing when it says "giving file to customer." Are you starting a download? – Evan Mulawski Nov 29 '10 at 13:28
  • whats the error-message you're facing? sounds like there should be something like "can't set header information, headers olready sent on..." (wich should be self-explanatory) – oezi Nov 29 '10 at 13:28
  • 1
    giving file to customer starts the file download, but then after that's finished I'd like to redirect the page. – akano1 Nov 29 '10 at 13:30

4 Answers4

4

It's impossible to output the header after you have output the file. Headers need to go first (hence the name). If you would output the header before you output the file, a browser would be free to ignore the body. I'm not sure what browsers actually do, but I doubt both a redirect and a file download will be initiated simultaneously. One or the other would probably be ignored.

Basic fact: You cannot output any information apart from what's necessary for the file download in the same response as the file download. The header of the file download response can only contain information regarding the file, the response body can only contain the file (i.e. no <meta> refreshes or such, those would become part of the file).

To illustrate, this would be what the browser receives:

HTTP/1.1 200 OK
Content-Type: application/pdf
Content-Disposition: attachment; filename=foo
Content-Length: 42

woieufhm23umh29… (file contents as binary gibberish) …cQ3985fno1rHtn3f
qo8923r10d30<meta http-equiv="refresh" content="1;url=../checkout.php">

Everything after the first blank line would be saved as the file contents, including the <meta> tag. You would actually corrupt the file by outputting any additional content there.

The way this usually works is to present the user with a "download page", which has an auto-refresh meta tag and/or Javascript, which first initiates the download, then on the second refresh redirects.

deceze
  • 510,633
  • 85
  • 743
  • 889
  • The refresh header can also be sent via PHP - no need for those ugly meta http-equiv tags from times where it wasn't easy to send an actual HTTP header. – ThiefMaster Nov 29 '10 at 13:35
  • 1
    Also, check this question - http://stackoverflow.com/questions/822707/php-generate-file-for-download-then-redirect – Buggabill Nov 29 '10 at 13:35
  • @Thief Sure, but it's hard to send a file download redirect *and* redirect-to-next-page. Then you arrive right at the problem the OP has. IMO these redirect-after-download pages are completely antiquated, meta tag refreshes are the lesser evil. – deceze Nov 29 '10 at 13:37
  • 1
    thanks for the reply, but just wondering how do I use the second refresh to start the download,say I take the user to the redirect page first, then how can I refresh the page to start the download. – akano1 Nov 29 '10 at 14:03
  • 1
    @amir You could keep track on the server whether the file was already downloaded or not. If yes, redirect instead of offering the file. It's probably easier using Javascript though. Since neither method is 100% reliable, you should not actually depend on this feature always working, in fact, IMO, as I said above, you should stop using the download-redirect pattern at all. – deceze Nov 29 '10 at 14:20
2

I had a workaround. The page where I send the file I opened with a target="_blank", on first page I did a onclick JavaScript redirect or show div.

The page that opens to send the file, starts the download and immediately closes.

Hope this helps.

MeSo2
  • 450
  • 1
  • 7
  • 18
0

Your code immediately sends the file contents to the user, i.e. it starts a download. If you want to start the download and display another page, display the page and - on this page - send this header: header('Refresh: 2;url=url/to/your/download');

As the browser will start a download it will not redirect away from the displayed page.

ThiefMaster
  • 310,957
  • 84
  • 592
  • 636
0

Just posting this as I was working on this for a minute too trying to redirect and download a file after a user submits a form. Solution was embedding the PHP file that runs readfileDownloader.php in an iframe on the form processing page, then refreshing on that page works. My readfileDownloader.php uses application/octet-stream to avoid the iFrame potentially trying to actually display the target file.

    // iFrame to load the file downloader php file
    echo '<iframe id="my_iframe" style="display:none;"></iframe>';
    echo '<script>';
    echo "document.getElementById('my_iframe').src = \"readfileDownloader.php\";";
    echo '</script>';

    // Redirects. Refresh must at least be 1.
    header('Refresh: 1;url=final_location.html');
Andrew
  • 1
  • 1