PHP / Javascript: Как я могу ограничить скорость загрузки?

У меня есть следующий сценарий:
Вы можете скачать с нашего сервера несколько файлов. Если вы «обычный» пользователь, у вас ограниченная пропускная способность, например, 500 кбит. Если вы являетесь премиум-пользователем, у вас нет предела пропускной способности и вы можете загружать его максимально быстро. Но как я могу это понять?
Как это загружено & сотрудничать?

11

Решение

Примечание: вы Можно сделать это с помощью 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>
6

Другие решения

Ты можешь использовать 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 убил ваш скрипт.

1

Есть эта библиотека пользователя земли 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);
1
По вопросам рекламы [email protected]