У меня есть следующий сценарий:
Вы можете скачать с нашего сервера несколько файлов. Если вы «обычный» пользователь, у вас ограниченная пропускная способность, например, 500 кбит. Если вы являетесь премиум-пользователем, у вас нет предела пропускной способности и вы можете загружать его максимально быстро. Но как я могу это понять?
Как это загружено & сотрудничать?
Примечание: вы Можно сделать это с помощью PHP, но я бы порекомендовал вам позволить самому серверу обрабатывать регулирование. Первая часть этого ответа посвящена вашим вариантам, если вы хотите ограничить скорость загрузки только с помощью PHP, но ниже вы найдете пару ссылок, в которых вы найдете, как управлять лимитами загрузки с помощью сервера.
Существует расширение PECL, которое делает это довольно тривиальной задачей, называемой pecl_http, который содержит функцию http_throttle
. Документы содержат простой пример того, как это сделать уже. Это расширение также содержит HttpResponse
учебный класс, который не очень хорошо документирован, но я подозреваю, что setThrottleDelay
а также setBufferSize
методы должны давать желаемый результат (задержка газа => 0,001, размер буфера 20 == ~ 20 Кб / с). Судя по всему, это должно сработать:
$download = new HttpResponse();
$download->setFile('yourFile.ext');
$download->setBufferSize(20);
$download->setThrottleDelay(.001);
//set headers using either the corresponding methods:
$download->setContentType('application/octet-stream');
//or the setHeader method
$download->setHeader('Content-Length', filesize('yourFile.ext'));
$download->send();
Если вы не можете / не хотите устанавливать это, вы можете написать простой цикл:
$file = array(
'fname' => 'yourFile.ext',
'size' => filesize('yourFile.ext')
);
header('Content-Type: application/octet-stream');
header('Content-Description: file transfer');
header(
sprintf(
'Content-Disposition: attachment; filename="%s"',
$file['fname']
)
);
header('Content-Length: '. $file['size']);
$open = fopen($file['fname'], "rb");
//handle error if (!$fh)
while($chunk = fread($fh, 2048))//read 2Kb
{
echo $chunk;
usleep(100);//wait 1/10th of a second
}
Конечно, не буферизируйте вывод, если вы делаете это :), и может быть лучше добавить set_time_limit(0);
заявление тоже. Если файл большой, вполне вероятно, что ваш скрипт будет убит в середине загрузки, потому что он достигает максимального времени выполнения.
Другой (и, вероятно, предпочтительный) подход заключается в ограничении скорости загрузки через конфигурацию сервера:
Я никогда не ограничивал скорость загрузки, но, глядя на ссылки, я думаю, будет справедливо сказать, что nginx является самым простым:
location ^~ /downloadable/ {
limit_rate_after 0m;
limit_rate 20k;
}
Это немедленно запускает ограничение скорости и устанавливает его на 20 КБ. Подробности можно найти на Nginx Wiki.
Что касается Apache, это не тот намного сложнее, но для этого потребуется включить модуль ratelimit
LoadModule ratelimit_module modules/mod_ratelimit.so
Затем достаточно просто сообщить apache, какие файлы нужно регулировать:
<IfModule mod_ratelimit.c>
<Location /downloadable>
SetOutputFilter RATE_LIMIT
SetEnv rate-limit 20
</Location>
</IfModule>
Ты можешь использовать http_throttle
от pecl_http
Расширение PHP:
<?php
// ~ 20 kbyte/s
# http_throttle(1, 20000);
# http_throttle(0.5, 10000);
if (!$premium_user) {
http_throttle(0.1, 2000);
}
http_send_file('document.pdf');
?>
(Вышеуказанное основано на примере из http://php.net/manual/en/function.http-throttle.php.)
Если ваш сервер API не позволяет http_throttle
создайте два разных, не угадываемых URL для ваших премиум-пользователей и пользователей премиум-класса и обратитесь к документации вашего HTTP-сервера, чтобы узнать, как регулировать один из них. Увидеть https://serverfault.com/questions/179646/nginx-throttle-requests-to-prevent-abuse для примера для Nginx. Последнее имеет то преимущество, что позволяет обойти такие проблемы, как преждевременное завершение загрузки из-за того, что PHP убил ваш скрипт.
Есть эта библиотека пользователя земли PHP bandwidth-throttle/bandwidth-throttle
use bandwidthThrottle\BandwidthThrottle;
$in = fopen(__DIR__ . "/resources/video.mpg", "r");
$out = fopen("php://output", "w");
$throttle = new BandwidthThrottle();
$throttle->setRate(500, BandwidthThrottle::KIBIBYTES); // Set limit to 500KiB/s
$throttle->throttle($out);
stream_copy_to_stream($in, $out);