Ответ 1
Примечание: вы можете делать это с помощью PHP, но я бы рекомендовал вам позволить самому серверу обрабатывать дросселирование. Первая часть этого ответа касается того, каковы ваши варианты, если вы хотите ограничить скорость загрузки одним PHP, но ниже вы найдете пару ссылок, где вы найдете, как управлять ограничениями на скачивание с использованием сервера.
Существует расширение PECL, которое делает это довольно тривиальной задачей, называемой pecl_http, которая содержит функцию http_throttle
. Документы содержат простой пример того, как это сделать. Это расширение также содержит a HttpResponse
класс, который плохо документирован ATM, но я подозреваю, что играю с его 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);
. Если файл большой, вполне вероятно, что ваш script будет убит в середине загрузки, так как он достиг максимального времени выполнения.
Другим (и, вероятно, предпочтительным) подходом было бы ограничение скорости загрузки через конфигурацию сервера:
- используя NGINX
- с помощью Apache2
- с использованием MS IIS (либо установите модуль дросселирования битрейта, либо установите максимальную полосу пропускания)
Я никогда не ограничивал скорость загрузки самостоятельно, но, глядя на ссылки, я считаю справедливым сказать, что nginx является самым простым:
location ^~ /downloadable/ {
limit_rate_after 0m;
limit_rate 20k;
}
Это приводит к немедленному удару скорости и устанавливает значение 20k. Подробности можно найти на вики nginx.
Что касается 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>