限制PHP CURL上传和下载数据大小,防止爆内存后出错退出

在php中用curl读取网页,如果遇到网页大小巨大,curl会直接撑爆内存导致后续处理被中断。

以下是限制下载内容大小的方法,超过指定大小后,中断连接,抛弃已传输数据。

方法一:使用 CURLOPT_PROGRESSFUNCTION 回调。具体参数含义见:https://www.php.net/manual/zh/function.curl-setopt.php

    //curl_setopt($ch, CURLOPT_BUFFERSIZE, 512); // 可以调整缓冲大小,以展示更多进程信息
    curl_setopt($ch, CURLOPT_NOPROGRESS, false); //true 时关闭 cURL 的传输进度。PHP 默认自动设置此选项为 true,只有为了调试才需要改变设置。
    //五个参数,第一个是cURL的资源句柄,第二个是预计要下载的总字节(bytes)数。第三个是目前下载的字节数,第四个是预计传输中总上传字节数,第五个是目前上传的字节数。
    //请注意,php 5.5之前的版本没有第1个参数Resource_id,只有后面4个参数,使用时可能需要删除Resource_id这一项
    curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, function (
        $Resource_id,$DownloadSize, $Downloaded, $UploadSize, $Uploaded
    )
    {
        //兼容5.5之前的版本,如果使用的是5.5之后的版本,可将此判断删除
        if (version_compare(PHP_VERSION, '5.5.0') < 0) {        
            $Uploaded= $UploadSize;
            $UploadSize= $Downloaded;
            $Downloaded= $DownloadSize;
            $DownloadSize= $Resource_id;
            $Resource_id = '';
        }
    
        // 测试过程中输出的信息,正式环境请将下面一行删除
        echo '$Resource_id = '.$Resource_id, ' - ','$DownloadSize = '.$DownloadSize, ' - ', '$Downloaded = '.$Downloaded, ' - ', '$UploadSize = '.$UploadSize, ' - ', '$Uploaded = '.$Uploaded, ' - '.round(memory_get_usage() / 1024 / 1024, 2).'MB'."\n";
        //如果下载超过10MB,则返回非零值将中断传输,传输将设置 CURLE_ABORTED_BY_CALLBACK 错误:Callback aborted。如果要限制上限,则使用 $Uploaded 来限制。
        return ($Downloaded > (10 * 1024 * 1024)) ? 1 : 0;
    });


方法二:使用 CURLOPT_WRITEFUNCTION 

此方法可以超过指定大小后,中断连接,保留已传输数据。但依然有一定机率出错,导致整条程序崩溃。

未测试成功,此处代码略。