Я обслуживаю загрузки с URL-адреса своим пользователям с помощью PHP-скрипта. При использовании readfile()
я получаю максимальную скорость загрузки, которую может поддерживать мое соединение (около 2,5 МБ / с), однако, когда я использую маршрут fopen, fread, fclose
скорость загрузки очень, очень медленная (около 1-2 КБ / с).
Вот мой код:
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); }
и код readfile – это просто readfile($link);
,
Я не могу просто использовать readfile()
из-за двух причин: один из них – это ограничение скорости загрузки пользователей (что я могу сделать с fread
, просто считывая столько данных), и я также хочу отслеживать, сколько пользователь (я могу сделать это с помощью readfile()
но он не учитывает частичные загрузки).
Кто-нибудь знает, почему это может произойти или как я могу это исправить? Насколько я знаю, readfile()
– это просто оболочка для fopen, fread and fclose
поэтому я не понимаю, что происходит.
Изменить: закончилось с cURL для этого.
$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; }
Используйте stream_context_create () и stream_get_contents ()
$context = stream_context_create(); $file = fopen($url, 'rb', FALSE, $context); while(!feof($file)) { //usleep(1000000); echo stream_get_contents($file, 2014); }
в$context = stream_context_create(); $file = fopen($url, 'rb', FALSE, $context); while(!feof($file)) { //usleep(1000000); echo stream_get_contents($file, 2014); }
Вы также можете попытаться сделать длину чтения файла более крупной и положить в usleep (), чтобы замедлить выполнение. По-видимому, функции потока по-прежнему рекомендуются для fread для последней версии PHP. Возможно, вы захотите также добавить @ перед файлом fread () или stream_get_contents (), чтобы подавить любые ошибки, по крайней мере, на производстве. Без него, и небольшая неудача, и у вас есть поврежденный файл.
Это может быть буферизация (или, возможно, ограничение скорости) где-то в PHP или Apache. Попробуйте изменить:
while(!feof($file)) { echo fread($file, 2014); }
Для того, чтобы:
while(!feof($file)) { $s=fread($file, 2014); if($s===false)break; //Crude echo $s; @ob_flush();@flush(); }
(Префикс @
– это потому, что они могут жаловаться на пустые буферы.)
Как сказал mr.freshwater, у вас должна быть проверка ошибок на вашем fread
звонке, поэтому я добавил что-то основное выше.
Причина в 2014. OS получает 4096 байт данных очень быстро, а затем другие. Но если вы пишете 2014, тогда ОС пытается прочитать данные из файла на один байт, чтобы вычислить его. Вот почему так долго. Изменить 2014 – 4096