Running PHP/Apache on localhost. Yes, very old versions (Apache/2.4.10 (Win32) PHP/5.4.34), but the code has worked for years. I had been relying on the Xsendfile Apache module, but that failed silently. Changed to use explicit calls to header() and echo contents. That causes Chrome to say "Couldn't finish download". And Firefox says "example.zip.part could not be saved, because the source file could not be read. Try again later, or contact the server administrator."
Chrome 117.0.5938.89 (Official Build) (64-bit), Firefox 117.0.1 (64-bit) on Windows 10.
Here is the code:
if (false && in_array('mod_xsendfile', apache_get_modules())) { // Despite the documentation in https://tn123.org/mod_xsendfile/beta/, simply encoding // the pathname with urlencode causes X-Sendfile to provoke an internal server error. // See http://stackoverflow.com/questions/2676 ... ile-expect $encoded = str_replace('%2F', '/', rawurlencode($pathname)); header("Content-Type: $mime_info"); if ($attachment === true) { $dispo = 'attachment'; } else { $dispo = 'inline'; } header("Content-Disposition: $dispo; filename=\"$basename\""); // xsendfile makes apache generate headers and body for best download behavior. header("X-SendFile: $encoded"); } else { // At least one post somewhere said these were good headers for manual download header("Pragma: public"); header("Expires: 0"); header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); header("Cache-Control: private", false); // required for certain browsers header("Content-Type: $mime_info"); if ($attachment === true) { header("Content-Disposition: attachment; filename=\"$basename\""); } header("Content-Length: " . filesize("$pathname")); ob_clean(); flush(); $data = file_get_contents("$pathname"); echo $data; } I just tossed the "false &&" into the "if" to force it not to use the Xsendfile module. And, as I said, that changed the behavior from silent failure in Chrome (nothing in the UI indicating that a download was attempted at all), to having the download start (saying 0/32.1 KB, 38 seconds left for a while), then finally "Couldn't finish download".
I'm totally stumped! This same code has worked before on my PC downloading the same file (using the Xsendfile module). I normally pass in $attachment = true; but also tried it with $attachment = false, with no improvement.
As the comments note, the pragmas and cache-control stuff was just copied from some post somewhere. It has been working on a public site for the last 12 years or so...
EDIT: FWIW, I've tried two more things I've seen posted regarding problems with downloads:
- Open an Incognito window to do the down. No change in behavior.
- Add header: header("Content-Transfer-Encoding: Binary"); Again, no change in behavior.
BTW, I am running ESET Internet Security 16.2.13.0, but I have disabled its firewall, and also turned off virus scanning for these tests. But again, no change in results...
*** UPDATE *** I've also tried removing the Pragma:, Expires:, and Cache-control: headers, again without any effect.
The only way I've been able to download this small (37KB) zip file is by making it the href attribute of an element which also has the download attribute. So I guess I'll try to cook up something that does that. The current code is nice in that I don't have to create the zip file until a user asks to download it, and the path from the web root is not revealed to the user. With a static element, I'll have to keep the zip file up-to-date with any changes made by the user, and the path to it will be visible to the user. Although I could maybe use javascript to create the element dynamically and trigger a click on it, allowing me to create the zip file only when requested, and hiding the path from all but highly inquisitive users. What an incredible pain!
Источник: https://stackoverflow.com/questions/771 ... -with-both