Question

In my function I'm downloading a file that saves downloads to a log file. Whenever I try to download an Excel file I uploaded, Excel states that it is corrupted. My local copy works fine. Here is my download.php:

<?php
include_once 'includes/db_connect.php';
include_once 'includes/functions.php';

sec_session_start();
ob_start();
?>

<?php if (login_check($mysqli) == true) :?>
<?php
$logFile = "download.log";
$directory = "./downloads/";
date_default_timezone_set('America/New_York');

$filename = $_GET['file'];
$path = "$directory$filename";
if(file_exists($path) AND substr_count($filename,"/") == "0") {
  if (isset($logFile)) {
    $downloadLogRecord = $filename." || ".$_SESSION['name']." || ".$_SESSION['username']." || ".$_SERVER['REMOTE_ADDR']." || ".date('Y-m-d H:i:s')."\r\n";
    @file_put_contents($logFile,$downloadLogRecord,FILE_APPEND|LOCK_EX);
  }
  header("Content-type: application/octet-stream"); 
  header("Content-Disposition: attachment; filename=$filename"); 
  header("Content-Length: ".filesize($path));
  readfile("$path");
}
?>
<?php else : ?>
  <p>
    <span class="error">You are not authorized to access this page.</span> Please <a href="index.php">login</a>.
  </p>
<?php endif; ?>

How can I fix this?

Was it helpful?

Solution

Figured it out. I simply added ob_get_clean(); before readfile(); and ob_end_flush(); after it.

OTHER TIPS

Keep in mind you can have nested output buffers, and this will corrupt your download as well (cheers to Vladamir for figuring this out). So to clear the output buffer completely (instead of just running ob_end_clean();) run this before you read your file:

while (ob_get_level()) {
    ob_end_clean();
}   

This will clear out your entire buffer and you won't have any extra characters to mess up your download.

I also had the same situation: In my function I was downloading a PDF file, and the file always downloads corrupted, I spent hours giggling around, nothing helped, finally:

I had to add die(); or exit(); as the last line, because I was using a MVC Framework, and MVC was causing to render view after action was finished.

Bottom line: make sure you do not have any code executed after the last line readfile(FILE_NAME)

I had the same problem in Laravel, I tried these solutions but didn't work. I used return readfile($doc) which was causing the problem .This is my working code:

header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename=" . basename($doc));
header("Content-Type: " . $file_extension);
//return readfile($doc);
readfile($doc);

I got the corrupted file error only for excel and others were working fine. But when i removed return from return readfile($doc); excel also worked fine.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top