PHP/Javascript:如何限制下载速度


PHP/Javascript: How I can limit the download speed?

>我有以下情况:您可以从我们的服务器下载一些文件。如果您是"普通"用户,则带宽有限,例如500kbits。如果您是高级用户,则带宽没有限制,可以尽快下载。但是我怎么能意识到这一点呢?这是如何上传的?

注意:你可以用PHP做到这一点,但我建议你让服务器本身处理限制。本答案的第一部分涉及如果您想仅使用 PHP 来限制下载速度,您的选择是什么,但在下面您将找到几个链接,您可以在其中找到如何使用服务器管理下载限制。

有一个PECL扩展使它成为一个相当微不足道的任务,称为pecl_http,其中包含函数 http_throttle .文档包含有关如何执行此操作的简单示例。此扩展还包含一个 HttpResponse 类,该类没有很好的文档 ATM,但我怀疑使用它的setThrottleDelaysetBufferSize方法应该会产生所需的结果(油门延迟 => 0.001,缓冲区大小 20 == ~20Kb/秒(。从外观上看,这应该有效:

$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
  • 使用 Apache2
  • 使用 MS IIS(安装比特率限制模块,或设置最大带宽(

我自己从来没有限制过下载率,但看看链接,我认为可以公平地说nginx是迄今为止最简单的:

location ^~ /downloadable/ {
    limit_rate_after 0m;
    limit_rate 20k;
}

这使得速率限制立即启动,并将其设置为 20k。 详细信息可以在nginx维基上找到。

就 apache 而言,它并没有那么难,但它需要你启用速率限制模块。

LoadModule ratelimit_module modules/mod_ratelimit.so

然后,告诉 apache 应该限制哪些文件很简单:

<IfModule mod_ratelimit.c>
    <Location /downloadable>
        SetOutputFilter RATE_LIMIT
        SetEnv rate-limit 20
    </Location>
</IfModule>

您可以使用 pecl_http PHP 扩展中的http_throttle

<?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 服务器的文档,了解如何限制其中一个 URL。有关 Nginx 的示例,请参见 https://serverfault.com/questions/179646/nginx-throttle-requests-to-prevent-abuse。后者的好处是允许您回避诸如由于 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);