如何在此PHP代码中限制下载速度

时间:2019-04-03 13:49:46

标签: php downloading rate-limiting download-manager

我有以下与我的网站的下载方法有关的PHP代码。我正在尝试将下载速度限制为特定的速度,因为当前下载管理器正在滥用和挤占下载速度。

不幸的是,我没有编码经验。

public function download(
    $file,
    $filename,
    $file_size,
    $content_type,
    $disposition = 'inline',
    $android = false
) {
    // Gzip enabled may set the wrong file size.
    if (function_exists('apache_setenv')) {
        @apache_setenv('no-gzip', 1);
    }
    if (ini_get('zlib.output_compression')) {
        @ini_set('zlib.output_compression', 'Off');
    }
    @set_time_limit(0);
    session_write_close();
    header("Content-Length: ".$file_size);

    if ($android) {
        header("Content-Type: application/octet-stream");
        header("Content-Disposition: attachment; filename=\"".$filename."\"");
    } else {
        header("Content-Type: $content_type");
        header("Content-Disposition: $disposition; filename=\"".$filename."\"");
        header("Content-Transfer-Encoding: binary");
        header("Expires: -1");
    }
    if (ob_get_level()) {
        ob_end_clean();
    }
    readfile($file);
    return true;
}

1 个答案:

答案 0 :(得分:0)

  

代码:

<?php 
public function download(
    $file,
    $filename,
    $file_size,
    $content_type,
    $disposition = 'inline',
    $android = false
) {
    // Gzip enabled may set the wrong file size.
    if (function_exists('apache_setenv')) {
        @apache_setenv('no-gzip', 1);
    }
    if (ini_get('zlib.output_compression')) {
        @ini_set('zlib.output_compression', 'Off');
    }
    @set_time_limit(0);
    session_write_close();
    header("Content-Length: ".$file_size);

    if ($android) {
        header("Content-Type: application/octet-stream");
        header("Content-Disposition: attachment; filename=\"".$filename."\"");
    } else {
        header("Content-Type: $content_type");
        header("Content-Disposition: $disposition; filename=\"".$filename."\"");
        header("Content-Transfer-Encoding: binary");
        header("Expires: -1");
    }
    if (ob_get_level()) {
        ob_end_clean();
    }

    $this->readSlow($file, 1);

    return true;
}

private function readSlow(string $filename, int $sleepAmount = 0, int $chunkSize = 409600)
{
    $handle = fopen($filename, "r");

    while (!feof($handle)) {
        echo fread($handle, $chunkSize);
        ob_flush();
        sleep($sleepAmount);
    }
    fclose($handle);
}
  

注意:

我假设您发布了课程的一部分。如果您想在课堂外使用readSlow(),请按以下方式使用它:

readSlow('pathToFile', $amountOfSleep, $amountOfBytesToReadAtOneRead);

这是可选的

ob_flush();

我这样做了,所以一旦读取了缓冲区,它就会立即发送给请求数据的客户端,但是对于您而言,最好将其删除-测试{{1}的不同值是否适合使用它}和$amountSleep

sleep()不会消耗脚本的全部执行时间,因此,如果文件下载在10秒内没有任何睡眠,并且php脚本的最大执行时间为30秒,那么您可以轻松地使脚本运行通过睡眠,每次下载120秒。
除了使用sleep()之外,您还可以使用usleep()来对速度限制进行更精确的控制,因为它花费的睡眠时间以微秒为单位,而不是秒,因此在使用时以及如果您想在两次读取之间进入睡眠状态1秒钟,然后在使用usleep()时将$chunkSize设置为1000000

$sleepAmount是要读取的字节数,然后脚本将进入睡眠状态。玩这个值以获得最佳速度。

我没有测试代码,因此它可能无法正常工作,但至少这是从头开始的想法。