views:

49

answers:

2

I use the following to download a file with PHP:

  ob_start();

   $browser = id_browser();
   header('Content-Type: '.(($browser=='IE' || $browser=='OPERA')?
      'application/octetstream':'application/octet-stream'));
   header('Expires: '.gmdate('D, d M Y H:i:s').' GMT');
   header('Content-Transfer-Encoding: binary');
   header('Content-Length: '.filesize(realpath($fullpath)));
   //header("Content-Encoding: none");

   if($browser == 'IE')
   {
    header('Content-Disposition: attachment; filename="'.$file.'"');
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
    header('Pragma: public');
   } else 
   {
    header('Content-Disposition: attachment; filename="'.$file.'"');
    header('Cache-Control: no-cache, must-revalidate');
    header('Pragma: no-cache');
   }


   //@set_time_limit( 0 );
   ReadFileChunked(utf8_decode($fullpath));   

   ob_end_flush();

The source code of ReadFileChunked is:

function ReadFileChunked($filename,$retbytes=true) 
{
 $chunksize = 1*(1024*1024); 
 $remainFileSize = filesize($filename);

 if($remainFileSize < $chunksize)
  $chunksize = $remainFileSize;

 $buffer = '';
 $cnt =0;
 // $handle = fopen($filename, 'rb');
 //echo $filename."<br>";
 $handle = fopen($filename, 'rb');
 if ($handle === false) {
  //echo 1;
  return false;
 }
 //echo 2;
 while (!feof($handle)) 
 {  
  //echo "current remain file size $remainFileSize<br>";
  //echo "current chunksize $chunksize<br>";
  $buffer = fread($handle, $chunksize);
  echo $buffer;
  sleep(1);
  ob_flush();
  flush();
  if ($retbytes) {
   $cnt += strlen($buffer);
  }

  $remainFileSize -= $chunksize;
  if($remainFileSize == 0)
   break;

  if($remainFileSize <  $chunksize)
  {
   $chunksize = $remainFileSize;   
  }
 }

 $status = fclose($handle);
 if ($retbytes && $status) {
  return $cnt; // return num. bytes delivered like readfile() does.
 }
 return $status;
}

The question is : The file downloaded will contiain some html tags which are the content of the html code generated by the php.

The error will happened when downloading the txt file with the file size smaller than 4096 bytes.

Please help me to slove this problem , thank you very much!

Chu

+1  A: 

Have you tried using fpassthru rather than your custom function.

Yacoby
A: 

There's no need to use the $chunksize stuff in there. fread() automatically stops reading once it reaches the end of the file, even if the $chunksize would normally tell it to read more. As well, you should probably put your ob_flush() and flush() calls BEFORE the sleep(1). That way the data you've just placed in the output buffer can get sent off to the webserver without having to wait the one second needlessly.

In fact, you could replace the whole function with the following:

function ReadFileChunk($filename, $retbytes = true) {
    $fh = fopen($filename, 'rb');
    if (!$fh) {
        return(false);
    }
    while($buf = fread($fh, 4096)) {
         echo $buf;
         ob_flush();
         flush();
         sleep(1);
    }
    $status = fclose($fh);

   return( $retbytes ? filesize($filename) : $status);
}

But why bother rolling your own when readfile() already exists? It will handle the whole business of opening the file, and sending it in normal-sized pieces that won't exceed memory_limit.

Marc B