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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17641073/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 16:12:54  来源:igfitidea点击:

How to set a maximum size limit to PHP cURL downloads?

phpcurl

提问by Sojan V Jose

Is there a maximum size limit to PHP cURL downloads? ie. will cURL quit when transfer reaches a certain file limit?

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

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

It's for a site that downloads remote images. I want to ensure that cURL will stop when it reaches a certain limit.

它适用于下载远程图像的站点。我想确保 cURL 在达到某个限制时会停止。

Also my research shows getimagesize()downloads the image, to return its size so its not an option.

此外,我的研究显示getimagesize()下载图像以返回其大小,因此它不是一种选择。

回答by CodeAngry

I have another answer that addresses the situation even better to leave here for posterity.

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

CURLOPT_WRITEFUNCTIONis good for this but CURLOPT_PROGRESSFUNCTIONis the best.

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;
});

Keep in mind that even if the PHP.net states^for CURLOPT_PROGRESSFUNCTION:

请记住,即使PHP.net 声明^CURLOPT_PROGRESSFUNCTION

A callback accepting five parameters.

接受五个参数的回调。

My local tests have featured only four (4) parametersas the 1st (handle)is not present.

我的本地测试只有四 (4) 个参数,因为第一个(句柄)不存在。

回答by CodeAngry

There is.It's the PHP memory limit, I presume. As the download is done in memory...

有。我想这是 PHP 内存限制。由于下载是在内存中完成的...

But CURLOPT_FILEand CURLOPT_WRITEHEADER^are your friends as they allow you to reroute the cURLdownload to streams.This allows you to create tmpfile()temporary streams (stream_get_meta_data()gives you the file path)and download to them. And downloading directly to drive lifts the memory limitations.

但是,CURLOPT_FILECURLOPT_WRITEHEADER^是你的朋友,因为他们让你重新路由cURL下载到流。这允许您创建tmpfile()临时流stream_get_meta_data()为您提供文件路径)并下载到它们。直接下载到驱动器解除了内存限制。

Once the download completes, you get to read those files and do what you wish with them.

下载完成后,您可以阅读这些文件并使用它们做您想做的事情。

回答by Dr ZIZO

The server does not honor the Range header. The best you can do is to cancel the connection as soon as you receive more data than you want. Example:

服务器不接受 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;

Perhaps more cleanly, you could use the http wrapper (this would also use curl if it was compiled with --with-curlwrappers). Basically you would call fread in a loop and then fclose on the stream when you got more data than you wanted. You could also use a transport stream (open the stream with fsockopen, instead of fopen and send the headers manually) if allow_url_fopen is disabled.

也许更简洁,您可以使用 http 包装器(如果使用 --with-curlwrappers 编译,也将使用 curl)。基本上你会在循环中调用 fread ,然后当你得到比你想要的更多的数据时在流上调用 fclose 。如果 allow_url_fopen 被禁用,您还可以使用传输流(使用 fsockopen 打开流,而不是 fopen 并手动发送标头)。