PHP Curl:逐步读取

时间:2009-09-09 02:06:14

标签: php curl

我有一个PHP脚本,它应该接收一个URL并在数据库中搜索URL的缓存版本。如果找到它,它会将缓存版本打印出来给用户,否则它会使用cURL下载并回复给用户。目前,下载脚本如下所示:

// create a new cURL resource
$ch = curl_init();
// set URL and other appropriate options
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1); 
// grab URL and pass it to the browser
$data = curl_exec($ch);
$mimetype = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
// close cURL resource, and free up system resources
curl_close($ch);

mysql_query("INSERT INTO `cache_files` (`key`, `original_url`, `file_data`, `mime_type`) VALUES (".
    "'" . mysql_real_escape_string($key) . "', " .
    "'" . mysql_real_escape_string($url) . "', " .
    "'" . mysql_real_escape_string($data) . "', " .
    "'" . mysql_real_escape_string($mimetype) . "')"
);

if (isset($_GET["no_output"])) die;

header ("Content-Type: " . $mimetype);
header ('Expires: '.gmdate('D, d M Y H:i:s \G\M\T', time() + 157680000), true);
header ('Last-Modified: '.gmdate('D, d M Y H:i:s \G\M\T'), true);
header ('Cache-Control: public; max-age=157680000');
header ('Pragma: ');
print $data;

这当前工作正常,但是,大文件在100%下载之前不会发送给最终用户,这会导致不会触发增量渲染。我想知道cURL是否可以在下载时将数据传递给用户,还可以在字符串中使用数据供脚本使用。

2 个答案:

答案 0 :(得分:2)

这是一个粗略且不完整(但工作)的类,用于测试CURLOPT_WRITEFUNCTION选项的使用。根据{{​​3}},只要收到需要保存的数据,libcurl就会调用此选项给出的函数。因此curl接收的内容应该在收到时传递给服务器。当它实际显示时,当然会依赖于服务器和浏览器。

$url = 'http://stackoverflow.com/';
$curl_test = new CurlCallbackTest($url);
file_put_contents('some.file', $curl_test->content);

class CurlCallbackTest
{
    public $content = '';

    public function __construct($url)
    {
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_WRITEFUNCTION, array($this, 'showContent'));
        curl_setopt($ch, CURLOPT_HEADER, false);
        curl_exec($ch);
        curl_close($ch);
    }

    private function showContent($ch, $data)
    {
        $this->setContent($data);
        echo htmlspecialchars($data);
        return strlen($data);
    }

    private function setContent($data)
    {
        $this->content .= $data;
    }
}

答案 1 :(得分:1)

您可以使用CURLOPT_WRITEFUNCTION回调来挂钩cURL的响应数据处理。示例(通过http://www.php.net/manual/en/function.curl-setopt.php#26239):

<?php

function myPoorProgressFunc($ch, $str) {
  global $fd;

  $len = fwrite($fd, $str);
  print('#');
  return $len;
}

curl_setopt($ch, CURLOPT_WRITEFUNCTION, 'myPoorProgressFunc');

而不是将数据写入文件并输出“#”,您可以将数据写入浏览器并将其保存为字符串。但是,对于大文件,我会对后者持谨慎态度。