title: fread a lot slower for downloads than readfile
body: <p>I'm serving downloads from a URL to my users through a PHP script. When using <code>readfile()</code> I get the maximum download speed my connection can support (about 2.5MB/s) however when I use the <code>fopen, fread, fclose</code> route the download speed is very, very slow (about 1-2KB/s).</p>
  
  <p>Here's my code:</p>
  
  <pre><code>header('Content-Description: File Transfer');
  header('Content-Type: application/octet-stream');
  header('Content-Disposition: attachment; filename=' . $filename);
  header('Content-Transfer-Encoding: binary');
  header('Expires: 0');
  header('Cache-Control: must-revalidate');
  header('Pragma: public');
  header('Content-Length: ' . $filesize);
  ob_clean();
  flush();
  
  $file = fopen($url, 'rb');
  
  while(!feof($file)) {
      echo fread($file, 2014);
  }
  </code></pre>
  
  <p>and the readfile code is simply <code>readfile($link);</code>.</p>
  
  <p>I can't just use the <code>readfile()</code> function because of two reasons, one is I want to restrict the users download speed (which I can do with <code>fread</code> by only reading so much data) and I also want to track how much a user is downloading (I can do this with <code>readfile()</code> but it doesn't count partial downloads).</p>
  
  <p>Does anyone know why this might be happening or how I can fix it? As far as I know <code>readfile()</code> is just a wrapper for <code>fopen, fread and fclose</code> so I don't get what's going wrong.</p>
  
  <p>Edit: Ended up going with cURL for this.</p>
  
  <pre><code>$curl = curl_init();
  $options = array(
      CURLOPT_URL =&gt; $rdLink,
      CURLOPT_FAILONERROR =&gt; true,
      CURLOPT_BINARYTRANSFER =&gt; true,
      CURLOPT_RETURNTRANSFER =&gt; true,
      CURLOPT_WRITEFUNCTION =&gt; 'readResponse'
  );
  curl_setopt_array($curl, $options);
  
  if(!curl_exec($curl)) {
      header('Location: http://whatever.com');
      exit;
  }
  curl_close($curl);
  
  function readResponse($ch, $data) {
      $length = mb_strlen($data, '8bit');
  
      echo $data;
  
      return $length;
  }
  </code></pre>