2009-09-09 45 views
1

我有一個PHP腳本,應該在URL中搜索並搜索數據庫以獲取緩存版本的URL。如果找到它,它將緩存的版本打印出來,否則使用cURL將其下載並將其回覆給用戶。目前,下載腳本看起來是這樣的:PHP 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是否可以在下載時將數據傳遞給用戶,還可以將字符串中的數據用於腳本消耗。

回答

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

,而不是將數據寫入到文件和輸出「#」,你可以寫數據到瀏覽器,並將其保存在字符串。不過,對於大文件,我會對後者保持謹慎。

2

下面是一個原始的和不完整的(但工作)類來測試使用CURLOPT_WRITEFUNCTION選項。根據libcurl documentation,此選項給出的函數「只要存在需要保存的數據,就會被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; 
    } 
}