-1

I have a page.php with a form, user click on the button and is redirected to download.php where I have the following code:

$zip_file = substr_replace($url, 'zip', strrpos($url, '.') + 1);
$zip_path = '/dev/' . $zip_file;
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename="' . $zip_file . '"');
readfile($zip_path);
unlink($zip_file);

header("Location: success.php");

Basically I was very happy because it works very well in local, the download starts and there is the redirect to the success page. When I upload my files on the server, I open page.php, I click on the button and I reach download.php but the download doesn't start, the redirect works, I'm redirected to success.php without any download. If comment the redirect, header(), the download starts, so it's not because of the code (I guess).

My problem is that it's just on the server that the download does not start before redirect, and I have no idea why. I need to remove the redirect to make it work but I can't do that.

I hope someone with more experience could help, thank you very much.

elliot
  • 13
  • 4
  • consider adding `ini_set('display_errors', 1);`, `ini_set('display_startup_errors', 1);` and `error_reporting(E_ALL);` to see what is the error. I guess that could be folder permissions – Julyano Felipe Mar 17 '23 at 18:28
  • Hi @JulyanoFelipe, thanks for answering. But as I wrote, if I comment the redirect the file can be downloaded. – elliot Mar 17 '23 at 18:30
  • 1
    I guess that you can't send more headers after you send your file – Julyano Felipe Mar 17 '23 at 18:34
  • You sould create font-end, calling an API to get the file and download and after redirect – Julyano Felipe Mar 17 '23 at 18:35
  • 2
    You can download, and you can redirect, but you cannot download then redirect with headers. It sends all of the headers at once, so the redirect will happen before the download can start. – aynber Mar 17 '23 at 18:36
  • @JulyanoFelipe could you give me an example in code please? It would be very helpful. Thank you! – elliot Mar 17 '23 at 18:36
  • @aynber but why it worked in local? And in this case, what is the best way to do it? – elliot Mar 17 '23 at 18:37
  • 1
    @elliot I just shared a very simple javascript code that do it – Julyano Felipe Mar 17 '23 at 18:43

2 Answers2

1

I'll share a very simple way with javascript to download file and redirect:

const zip_url = 'api_url_that_downloads_zip_file';
window.open(zip_url, '_blank');
window.location.replace('success.php');
Julyano Felipe
  • 288
  • 2
  • 22
  • I don't think that this is necessarily worth a downvote, but I don't think that this is any better than a `` redirect. `window.open()` simply _starts_ the download in another tab, and `window.location.replace()` will redirect to the "success" page regardless of if the download is actually successful or not. – Sammitch Mar 17 '23 at 19:36
0

The difference between the two installations is that output buffering is enabled on one, but not the other, and also error_reporting is either off or hidden on both.

The core problem is that you cannot issue a header() call after output has started, and readfile() will produce output.

The server on which the download works will have output buffering disable and not have a working redirect. If error reporting were on it would be producing an error message appended to the end of the file, likely causing an error on extract.

The server on which the download is not working has output buffering enabled and is able to actually process the header() call without error, but issuing a Location: header is an implicit 30X redirect which cannot have a body, aka contain the file.

You cannot have a download that redirects afterwards unless you use Javascript to handle those conditions client-side.

The closest you can get without JS is responding with a regular page that contains a <meta> redirect to the download, aka a "your download will start shortly" page.

<META HTTP-EQUIV='REFRESH' CONTENT='5;URL=http://www.example.com/download.php'>
Sammitch
  • 30,782
  • 7
  • 50
  • 77