如何设置 PHP cURL 下载的最大大小限制?

19

PHP cURL下载是否有最大大小限制?即,当传输达到某个文件大小限制时,cURL是否会退出?

curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
$data = curl_exec($ch);

这是一个下载远程图片的网站。我想确保cURL在达到某个限制时停止。

同时,我的研究显示getimagesize()会下载图片以返回其大小,因此不是一个选项。


你是想获取图像的字节大小还是其尺寸?curl仍会先下载文件。 - Lawrence Cherone
我想知道Curl是否默认设置了最大限制。如果下载出现问题,我不想让磁盘被占满。同时,我也想知道这个限制是否可以更改,比如通过php.ini文件。 - Sojan Jose
3个回答

33

我有另一个答案,更好地解决了这种情况,为了后人可以留在这里。

CURLOPT_WRITEFUNCTION 对此很好,但是 CURLOPT_PROGRESSFUNCTION 是最好的

// We need progress updates to break the connection mid-way
curl_setopt($cURL_Handle, CURLOPT_BUFFERSIZE, 128); // more progress info
curl_setopt($cURL_Handle, CURLOPT_NOPROGRESS, false);
curl_setopt($cURL_Handle, CURLOPT_PROGRESSFUNCTION, function(
    $DownloadSize, $Downloaded, $UploadSize, $Uploaded
){
    // If $Downloaded exceeds 1KB, returning non-0 breaks the connection!
    return ($Downloaded > (1 * 1024)) ? 1 : 0;
});

请记住,即使PHP.net网站^中针对CURLOPT_PROGRESSFUNCTION的说明如下:

一个接受五个参数的回调函数。

但是,在我的本地测试中,只有四个参数(不包括第一个参数(句柄))。


浏览了php.net页面并找到了类似的代码。只需添加以下内容:// 小缓冲区,提供更多进度信息/回调 curl_setopt($this->_Handle, CURLOPT_BUFFERSIZE, 128); - Sojan Jose
@SojanVJose 对的!对于你的需求,这是最好的方法。在示例代码中添加了你提到的选项。 - CodeAngry
1
已经使用不同的文件进行了测试,运行良好。将其更改为答案,因为这段代码更有用。 - Sojan Jose
3
在我的情况下,回调函数确实有五个参数。这只是想说,我们必须小心并自行测试该函数。 - Janis Peisenieks
2
在我的情况下,从回调函数返回非零值会导致下载结果为空。 curl_error 显示:“回调函数已中止”。 因此,我无法通过这种方式获取请求页面的部分内容。 - Yuri Gor
显示剩余2条评论

6

服务器不支持“Range”头。你所能做的最好的办法就是在你收到比你想要的更多数据时立即取消连接。例如:

<?php
$curl_url = 'http://steamcommunity.com/id/edgen?xml=1';
$curl_handle = curl_init($curl_url);

$data_string = "";
function write_function($handle, $data) {
global $data_string;
$data_string .= $data;
if (strlen($data_string) > 1000) {
    return 0;
}
else
    return strlen($data);
} 

curl_setopt ($curl_handle, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($curl_handle, CURLOPT_CONNECTTIMEOUT, 2);
curl_setopt ($curl_handle, CURLOPT_WRITEFUNCTION, 'write_function');

curl_exec($curl_handle);

echo $data_string;

也许更为简洁的方法是使用http包装器(如果编译时加上--with-curlwrappers,也会使用curl)。基本上你需要在循环中调用fread,然后在获取到比所需数据更多的数据时关闭流。如果allow_url_fopen被禁用,你也可以使用传输流(使用fsockopen打开流,而不是fopen,并手动发送标头)。

我想知道的是,是否有一些全局控制每个 PHP Curl 从服务器下载的内容的东西。类似于 upload_max_filesize。Codeangry 给出了答案。谢谢 :) - Sojan Jose

4

有的,可能是 PHP 内存限制。因为下载是在内存中完成的...

但是 CURLOPT_FILECURLOPT_WRITEHEADER^ 可以帮助你,它们允许你将 cURL 下载重定向到流。这样你就可以创建 tmpfile() 临时流 (stream_get_meta_data() 可以给出文件路径) 并将其下载到流中。直接下载到驱动器可以解决内存限制问题。

下载完成后,你可以读取这些文件并对它们进行处理。


虽然我想做的只是相反的,但 PHP 内存限制回答了我的最初问题。我想为了安全起见,在我的服务器上对 curl 请求的最大下载大小设置限制。希望有类似于 upload_max_filesize 的仅适用于 curl 的功能。 - Sojan Jose
1
@SojanVJose 使用 @DrZIZO 的建议,使用 CURLOPT_WRITEFUNCTION。但是请确保您需要设置的限制不要太大。虽然没有选项可以做到这一点,但如果您使用 CURLOPT_WRITEFUNCTION 并继续将数据附加到缓冲区中,直到达到限制为止,就可以实现这一点。 - CodeAngry
1
使用@drzizo的代码进行了尝试。看起来更容易实现,而且这种情况处理的限制也不是太大。 - Sojan Jose
@SojanVJose发布了一个新的答案。这是一个更合适的解决方案。请确保测试它,因为文档和实际使用之间存在一些差异。 - CodeAngry

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接