当前位置: 首页> 最新文章列表> 想控制下载进度并暂停?curl_pause 有哪些具体实现方法?

想控制下载进度并暂停?curl_pause 有哪些具体实现方法?

M66 2025-08-04

在使用 PHP 进行文件下载或抓取网络资源时,cURL 是最常用的工具之一。一般来说,我们使用 curl_exec() 来执行请求,并同步地等待请求完成。但在某些高级场景中,例如需要等,就必须用到 curl_pause() 这个函数。

本文将深入介绍 curl_pause() 的作用、使用场景,以及如何结合其他 cURL 函数实现更复杂的下载控制。

什么是 curl_pause()

curl_pause() 是 libcurl 提供的函数,用于控制正在进行中的传输操作,可以对接收(读取)或发送(写入)进行暂停或恢复。

在 PHP 中,这个函数的原型如下:

<span><span><span class="hljs-title function_ invoke__">curl_pause</span></span><span>(CurlHandle </span><span><span class="hljs-variable">$handle</span></span><span>, </span><span><span class="hljs-keyword">int</span></span><span> </span><span><span class="hljs-variable">$bitmask</span></span><span>): </span><span><span class="hljs-keyword">int</span></span><span>
</span></span>

其中 $bitmask 参数可以是以下常量的组合:

  • CURLPAUSE_RECV:暂停接收数据

  • CURLPAUSE_SEND:暂停发送数据

  • CURLPAUSE_ALL:暂停发送和接收

  • CURLPAUSE_CONT:继续传输(解除暂停)

返回值是 CURLcode 类型的状态码,通常为 0 表示成功。

典型使用场景

1. 实时控制下载任务

你可能需要根据带宽、用户操作或服务端响应来动态暂停下载。例如,当带宽紧张时,可以暂停某个下载任务,稍后再恢复。

<span><span><span class="hljs-variable">$ch</span></span><span> = </span><span><span class="hljs-title function_ invoke__">curl_init</span></span><span>(</span><span><span class="hljs-string">"https://example.com/largefile.zip"</span></span><span>);
</span><span><span class="hljs-variable">$fp</span></span><span> = </span><span><span class="hljs-title function_ invoke__">fopen</span></span><span>(</span><span><span class="hljs-string">"largefile.zip"</span></span><span>, </span><span><span class="hljs-string">"w"</span></span><span>);

</span><span><span class="hljs-title function_ invoke__">curl_setopt</span></span><span>(</span><span><span class="hljs-variable">$ch</span></span><span>, CURLOPT_FILE, </span><span><span class="hljs-variable">$fp</span></span><span>);
</span><span><span class="hljs-title function_ invoke__">curl_setopt</span></span><span>(</span><span><span class="hljs-variable">$ch</span></span><span>, CURLOPT_WRITEFUNCTION, function(</span><span><span class="hljs-variable">$ch</span></span><span>, </span><span><span class="hljs-variable">$data</span></span><span>) </span><span><span class="hljs-keyword">use</span></span><span> (&amp;$</span><span><span class="hljs-title">paused</span></span><span>) {
    </span><span><span class="hljs-title">static</span></span><span> $</span><span><span class="hljs-title">total</span></span><span> = 0;
    </span><span><span class="hljs-variable">$len</span></span><span> = </span><span><span class="hljs-title function_ invoke__">strlen</span></span><span>(</span><span><span class="hljs-variable">$data</span></span><span>);
    </span><span><span class="hljs-variable">$total</span></span><span> += </span><span><span class="hljs-variable">$len</span></span><span>;

    </span><span><span class="hljs-comment">// 模拟:下载到1MB就暂停</span></span><span>
    </span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-variable">$total</span></span><span> &gt;= </span><span><span class="hljs-number">1024</span></span><span> * </span><span><span class="hljs-number">1024</span></span><span> &amp;&amp; !</span><span><span class="hljs-variable">$paused</span></span><span>) {
        </span><span><span class="hljs-title function_ invoke__">curl_pause</span></span><span>(</span><span><span class="hljs-variable">$ch</span></span><span>, CURLPAUSE_RECV);
        </span><span><span class="hljs-variable">$paused</span></span><span> = </span><span><span class="hljs-literal">true</span></span><span>;
    }

    </span><span><span class="hljs-keyword">return</span></span><span> </span><span><span class="hljs-variable">$len</span></span><span>;
});

</span><span><span class="hljs-title function_ invoke__">curl_exec</span></span><span>(</span><span><span class="hljs-variable">$ch</span></span><span>);

</span><span><span class="hljs-comment">// 稍后恢复</span></span><span>
</span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-variable">$paused</span></span><span>) {
    </span><span><span class="hljs-title function_ invoke__">sleep</span></span><span>(</span><span><span class="hljs-number">5</span></span><span>); </span><span><span class="hljs-comment">// 假设我们等待5秒</span></span><span>
    </span><span><span class="hljs-title function_ invoke__">curl_pause</span></span><span>(</span><span><span class="hljs-variable">$ch</span></span><span>, CURLPAUSE_CONT);
    </span><span><span class="hljs-title function_ invoke__">curl_exec</span></span><span>(</span><span><span class="hljs-variable">$ch</span></span><span>);
}

</span><span><span class="hljs-title function_ invoke__">curl_close</span></span><span>(</span><span><span class="hljs-variable">$ch</span></span><span>);
</span><span><span class="hljs-title function_ invoke__">fclose</span></span><span>(</span><span><span class="hljs-variable">$fp</span></span><span>);
</span></span>

2. 与多线程 curl_multi 搭配使用

在使用 curl_multi_exec() 处理多个并发请求时,curl_pause() 更加重要。你可以精确地暂停某个 handle,而不会影响其他请求。

<span><span><span class="hljs-variable">$mh</span></span><span> = </span><span><span class="hljs-title function_ invoke__">curl_multi_init</span></span><span>();
</span><span><span class="hljs-variable">$chs</span></span><span> = [];

</span><span><span class="hljs-keyword">foreach</span></span><span> (</span><span><span class="hljs-variable">$urls</span></span><span> </span><span><span class="hljs-keyword">as</span></span><span> </span><span><span class="hljs-variable">$url</span></span><span>) {
    </span><span><span class="hljs-variable">$ch</span></span><span> = </span><span><span class="hljs-title function_ invoke__">curl_init</span></span><span>(</span><span><span class="hljs-variable">$url</span></span><span>);
    </span><span><span class="hljs-title function_ invoke__">curl_setopt</span></span><span>(</span><span><span class="hljs-variable">$ch</span></span><span>, CURLOPT_RETURNTRANSFER, </span><span><span class="hljs-literal">true</span></span><span>);
    </span><span><span class="hljs-title function_ invoke__">curl_multi_add_handle</span></span><span>(</span><span><span class="hljs-variable">$mh</span></span><span>, </span><span><span class="hljs-variable">$ch</span></span><span>);
    </span><span><span class="hljs-variable">$chs</span></span><span>[] = </span><span><span class="hljs-variable">$ch</span></span><span>;
}

</span><span><span class="hljs-comment">// 在某些条件下暂停某个请求</span></span><span>
</span><span><span class="hljs-title function_ invoke__">curl_pause</span></span><span>(</span><span><span class="hljs-variable">$chs</span></span><span>[</span><span><span class="hljs-number">0</span></span><span>], CURLPAUSE_RECV);

</span><span><span class="hljs-comment">// 恢复时:</span></span><span>
</span><span><span class="hljs-title function_ invoke__">curl_pause</span></span><span>(</span><span><span class="hljs-variable">$chs</span></span><span>[</span><span><span class="hljs-number">0</span></span><span>], CURLPAUSE_CONT);
</span></span>

注意事项

  • 并非所有服务器或传输都支持暂停恢复,尤其是在没有 Range 支持的服务器上,暂停可能等同于中断。

  • 如果使用 CURLOPT_RETURNTRANSFER,暂停后无法再使用 curl_exec() 获取剩余数据,需使用 curl_multi 或流式处理。

  • 暂停后数据仍可能在缓冲区中,因此你仍可能看到 WRITEFUNCTION 回调被调用一次。

总结

curl_pause() 为 PHP 提供了对 HTTP 传输行为的更细粒度控制,适用于需要动态控制数据流的高级场景,尤其在文件下载、流媒体处理、多线程任务控制等方面表现出巨大价值。

在使用时应结合 WRITEFUNCTION 回调与 curl_multi 环境,灵活管理传输状态。掌握它,可以为你的网络传输逻辑赋予前所未有的灵活性和控制力。