Intereting Posts
Как добавить строку строки в инкремент id в любой таблице? Как перенаправить пользователя в мобильное приложение или веб-сайт при нажатии гиперссылки, отправленной по электронной почте? Должно ли это быть обработано на стороне сервера с помощью PHP? Каков наилучший способ создания файла XLS в PHP? PHP get_called_class () альтернатива Как передать массив проверенных / непроверенных значений флажка в генератор электронной почты PHP? Ошибка: ожидаемая доктрина \ ORM \ Query \ Lexer :: T_WITH, получившая 'ON' PhpStorm не откроет файл моментального снимка профайлера xdebug Получить последнее слово строки Оператор Mysql SELECT с массивом php Как установить флажок «verify_peer_name = false» параметр контекста SSL через php.ini в PHP 5.6 Странное поведение Foreach Сочетание двух разных фильтров в одном Query – Elastica Как узнать, активен ли сеанс? php-mailer и html включают в себя переменные php cURL Загрузить Прогресс в PHP не работает?

Fread намного медленнее для загрузки, чем readfile

Я обслуживаю загрузки с 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