Fread is much slower to load than readfile
I am serving downloads from a url to my users via a PHP script. On use, readfile()
I get the maximum download speed my connection can support (about 2.5 MB / s), however, when I use the route fopen, fread, fclose
, the download speed is very, very slow (about 1-2 KB / s).
Here's my 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);
}
and the readfile code is simple readfile($link);
.
I can't just use the function readfile()
for two reasons: one - I want to limit the download speed of users (which I can do with fread
only reading out so much data), and I also want to track how much the user is downloading (I can do this with readfile()
, but he does not include partial downloads).
Does anyone know why this might be happening or how I can fix it? As far as I know, readfile()
this is just a wrapper for fopen, fread and fclose
so I don't understand what's going wrong.
Edit: ended up with cURL for this.
$curl = curl_init();
$options = array(
CURLOPT_URL => $rdLink,
CURLOPT_FAILONERROR => true,
CURLOPT_BINARYTRANSFER => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_WRITEFUNCTION => '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;
}
source to share
Use stream_context_create () and stream_get_contents ()
$context = stream_context_create();
$file = fopen($url, 'rb', FALSE, $context);
while(!feof($file))
{
//usleep(1000000);
echo stream_get_contents($file, 2014);
}
You can also try to increase the file read length and insert usleep () to slow down execution. Apparently thread functions are still recommended for fread for the latest PHP version. You might also want to add @ in front of fread () or stream_get_contents () to suppress any errors, at least in production. Without it and a bit of bad luck and you have a corrupted file.
source to share
It could be buffering (or maybe rate limiting) somewhere in PHP or Apache. Try to change:
while(!feof($file)) {
echo fread($file, 2014);
}
To:
while(!feof($file)) {
$s=fread($file, 2014);
if($s===false)break; //Crude
echo $s;
@ob_flush();@flush();
}
(The prefix @
is that they might complain about empty buffers.)
As mr.freshwater said, you must have error checking on your call fread
, so I added something basic above.
source to share