2013-06-30 3 views
3

Использование Curl в PHP, есть ли способ проверить заголовки HTTP-ответа до, загружая тело? Предположим, что я делаю запрос GET на некоторый URI, и я хочу захватить контент, только если Content-type - text/html. Я знаю, что сначала могу сделать запрос HEAD, а затем решить, следует ли использовать GET, но возможно ли это только в одном запросе?PHP/Curl: проверка заголовков ответов перед загрузкой тела

Я в основном ищу эквивалент следующего кода C#:

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://some.uri"); 
HttpWebResponse response = (HttpWebResponse)request.GetResponse(); 
if(response.ContentType.Equals("text/html")) { 
    string body = new StreamReader(response.GetResponseStream()).ReadToEnd(); 
} else { 
    // do nothing 
} 

Возможно ли это?

+0

сделал вы пробовали 'CURLOPT_HEADER 'и' CURLOPT_NOBODY'? – bystwn22

+0

@ bystwn22 'CURLOPT_NOBODY' делает curl отправляет запрос HEAD. Я знаю, что это можно сделать, используя HEAD + условный GET; то, что я ищу, это способ сделать это одним запросом. – zuza

+0

мм. да, понял, посмотрю мой ответ ниже, я надеюсь, что это сработает :) Если нет, простите меня, я noob :) – bystwn22

ответ

3

Да я получил, вы можете использовать CURLOPT_WRITEFUNCTION в этом случае.
Чтобы все было довольно быстро, я использую свой собственный класс curl во всех моих проектах.
Позвольте мне опубликовать это также.
Смотрите мой код ниже.

<?php 
    require_once("curl.class.php"); 

    /** variable to store response body **/ 
    $response_body = null; 
    /** total size of header in response **/ 
    $header_size = null; 

    /** initialize the curl object **/ 
    $curl = new ipCurl("http://example.com/images/someimage.jpg"); 
    /** set a read callback **/ 
    $curl->setReadCallback("my_read_callback"); 
    /** Include header in response **/ 
    $curl->includeHeader(); 
    /** start curl **/ 
    $curl->createCurl(); 

    if ($curl->getError() !== 0) { 
    /** something went wrong, print the error message, and error code **/ 
    echo $curl->getError().":".$curl->getErrorMessage(); 

    if ($curl->getError() === 23) { 
     // its not an image file (Failed writing body....) 
    } 
    } 
    else { 
    /** Everything fine, lets parse the body from response **/ 
    $response_body = substr($response_body, $header_size); 
    file_put_contents("image.jpg", $response_body); 
    } 

    /** The function for our curl write callback **/ 
    function my_read_callback(&$ch, $data) { 
    global $response_body, $header_size; 
    /** Get the content type **/ 
    $content_type = trim(curl_getinfo($ch, CURLINFO_CONTENT_TYPE)); 
    /** Give it time to get the content-type string from header **/ 
    if (!empty($content_type)) { 
     /** stop executing curl if its not an image **/ 
     if ($content_type !== "image/jpeg") { 
     return false; 
     } 
    } 
    /** size of the header **/ 
    $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE); 
    /** append resposne body to $response_body **/ 
    $response_body .= $data; 
    /** return current response length **/ 
    return strlen($data); 
    } 
?> 

Содержимое curl.class.php файл

<?php 
class ipCurl { 
    private $ch = null; 
    private $url = null; 

    private $_error = 0; 
    private $_errmsg = null; 
    private $_header = null; 
    private $_webpage = null; 
    private $_status = 0; 

    public function __construct($url = null) { 
    $this->url = $url; 

    if (!function_exists("curl_init")) { 
     throw new Exception("Fatal Error: Module 'Curl' is not installed properly"); 
    } 

    $this->ch = curl_init(); 

     curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true); 
     curl_setopt($this->ch, CURLOPT_FRESH_CONNECT, false); 
     curl_setopt($this->ch, CURLOPT_FORBID_REUSE, false); 

    $this->setTimout(40); 
    $this->setConnTimout(30); 
    $this->followLocation(); 
    $this->setMaxRedirects(4); 
    $this->excludeHeader(); 
    $this->includeBody(); 
    $this->verifySSL(); 
    $this->setBinaryTransfer(); 
    $this->setReferer($_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"]); 
    $this->setUserAgent(); 

    return $this; 
    } 

    public function __destruct() { 
    curl_close($this->ch); 
    $this->ch = null; 
    } 

    public function setReadCallback($callback = null) { 
    curl_setopt($this->ch, CURLOPT_WRITEFUNCTION, $callback); 
    return $this; 
    } 

    public function setProgressCallback($callback = null, $buffer = 128) { 
    curl_setopt($this->ch, CURLOPT_NOPROGRESS, false); 
    curl_setopt($this->ch, CURLOPT_PROGRESSFUNCTION, $callback); 
    curl_setopt($this->ch, CURLOPT_BUFFERSIZE, $buffer); 
    return $this; 
    } 

    public function includeHeader() { 
    curl_setopt($this->ch, CURLOPT_HEADER, true); 
    return $this; 
    } 
    public function excludeHeader() { 
    curl_setopt($this->ch, CURLOPT_HEADER, false); 
    return $this; 
    } 

    public function includeBody() { 
    curl_setopt($this->ch, CURLOPT_NOBODY, false); 
    return $this; 
    } 
    public function excludeBody() { 
    curl_setopt($this->ch, CURLOPT_NOBODY, true); 
    return $this; 
    } 

    public function setMaxRedirects($redirects = 4) { 
    if ($this->is_safe_mode()) { 
     return $this; 
    } 
    curl_setopt($this->ch, CURLOPT_MAXREDIRS, $redirects); 
    return $this; 
    } 

    public function followLocation() { 
    if ($this->is_safe_mode()) { 
     return $this->unfollowLocation(); 
    } 
    curl_setopt($this->ch, CURLOPT_FOLLOWLOCATION, true); 
    return $this; 
    } 
    public function unfollowLocation() { 
    curl_setopt($this->ch, CURLOPT_FOLLOWLOCATION, false); 
    return $this; 
    } 

    public function setReferer($referer = null) { 
    curl_setopt($this->ch, CURLOPT_REFERER, $referer); 
    return $this; 
    } 

    public function setBinaryTransfer($binary = false) { 
    curl_setopt($this->ch, CURLOPT_BINARYTRANSFER, $binary); 
    return $this; 
    } 

    public function setTimout($timeout) { 
    curl_setopt($this->ch, CURLOPT_TIMEOUT, $timeout); 
    return $this; 
    } 

    public function setConnTimout($timeout) { 
    curl_setopt($this->ch, CURLOPT_CONNECTTIMEOUT, $timeout); 
    return $this; 
    } 

    public function setUserAgent($userAgent = null) { 
    $userAgent = (!$userAgent) ? "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.64 Safari/537.31" : $userAgent; 
    curl_setopt($this->ch, CURLOPT_USERAGENT, $userAgent); 
    return $this; 
    } 

    public function setProxy($url = null, $port = 0, $username = null, $password = null) { 
    curl_setopt($this->ch, CURLOPT_PROXYAUTH, CURLAUTH_BASIC); 
    curl_setopt($this->ch, CURLOPT_PROXY, $url.(($port) > 0 ? ":".$port : null)); 

    if ($port > 0) { 
     curl_setopt($this->ch, CURLOPT_PROXYPORT, $port); 
    } 

    if ($username) { 
     curl_setopt($this->ch, CURLOPT_PROXYUSERPWD, $username.":".$password); 
    } 

    return $this; 
    } 

    public function setAuth($username = null, $password = null) { 
    curl_setopt($this->ch, CURLOPT_USERPWD, $username.':'.$password); 
    return $this; 
    } 

    public function setCookiFile($file = "cookie.txt") { 
    if (!$file) { 
     return $this; 
    } 
    curl_setopt($this->ch, CURLOPT_COOKIEJAR, $file); 
    curl_setopt($this->ch, CURLOPT_COOKIEFILE, $file); 
    return $this; 
    } 

    public function verifySSL($ssl = false) { 
    if (!$ssl) { 
     curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, false); 
     curl_setopt($this->ch, CURLOPT_SSL_VERIFYHOST, 2); 
    } 
    else { 
     curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, true); 
    } 
    return $this; 
    } 

    public function setPost($postFields = null, $keep_array = false) { 
    if (is_array($postFields) && !$keep_array) { 
     $postFields = http_build_query($postFields); 
    } 

    curl_setopt($this->ch, CURLOPT_POST, true); 
    curl_setopt($this->ch, CURLOPT_POSTFIELDS, $postFields); 

    return $this; 
    } 

    public function setFile($file = null) { 
    if ($file !== null) { 
     $file = realpath($file); 
    } 
    if ($file && is_readable($file)) { 
     $fp = fopen($file, "w"); 
     curl_setopt($this->ch, CURLOPT_FILE, $fp); 
    } 

    return $this; 
    } 

    public function setHeader($header = array("Expect:")) { 
    curl_setopt($this->ch, CURLOPT_HTTPHEADER, $header); 
    return $this; 
    } 

    public function createCurl($url = null) { 
    $url = ($url) ? trim($url) : trim($this->url); 

    if (!$url) { 
     throw new Exception("Fatal Error: you must provide a valid url before calling 'createCurl'"); 
    } 
    curl_setopt($this->ch, CURLOPT_URL, $url); 

    $this->_webpage = curl_exec($this->ch); 
    $this->_status = (int)curl_getinfo($this->ch, CURLINFO_HTTP_CODE); 
    $this->_error = (int)curl_errno($this->ch); 
    $this->_errmsg = curl_error($this->ch); 
    $this->_header = curl_getinfo($this->ch); 

    if (!$this->_errmsg) { 
     $this->_errmsg = $this->parse_http_code($this->_status); 
    } 

    return $this; 
    } 

    private function parse_http_code($code = 404) { 
    $code = (int)$code; 
    if (!class_exists("ipStatusCodes")) { 
     return null; 
    } 
    return ipStatusCodes::info($code); 
    } 

    private function is_safe_mode() { 
    return (@ini_get('open_basedir') != '' && @ini_get('safe_mode') != 'Off'); 
    } 

    public function getStatus() { 
    return $this->_status; 
    } 

    public function getResponse() { 
    return $this->_webpage; 
    } 

    public function getHeader() { 
    return $this->_header; 
    } 

    public function getError() { 
    return $this->_error; 
    } 

    public function getErrorMessage() { 
    return $this->_errmsg; 
    } 
} 
?> 

Я не заставляю вас использовать мой класс, вы можете просто использовать его как это также ...

<?php 
    curl_setopt($ch, CURLOPT_WRITEFUNCTION, "my_callback"); 
    function my_callback() { 
    // same like the "my_read_callback" function in my above code 
    } 
?> 
+1

. Отсутствующий ключевой фрагмент информации должен иметь обратный вызов -1, который вызывает ошибку и прерывает передачу. – goat

+0

@chris работает нормально, если 'CURLINFO_CONTENT_LENGTH_DOWNLOAD' возвращает' -1' как длину, только что проверил сейчас: нет ошибок, получил тело ответа успешно :) – bystwn22

+0

Параметры обратного вызова ('CURLOPT_HEADERFUNCTION',' CURLOPT_READFUNCTION', 'CURLOPT_WRITEFUNCTION' и 'CURLOPT_PROGRESSFUNCTION') - именно то, что мне нужно! Я не знал о них так +1 и принимаю. Благодаря! – zuza

0

с завитушкой заголовки могут быть прочитаны отдельно после выполнения запроса. выполнив следующий код

$ch = curl_init(); 
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
curl_setopt($ch, CURLOPT_VERBOSE, 1); 
curl_setopt($ch, CURLOPT_HEADER, 1); 

// Then, after your curl_exec call: 
$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE); 
$header = substr($response, 0, $header_size); 
$body = substr($response, $header_size); 
+0

Это не то, о чем я прошу. – zuza

+0

Это единственный способ сделать это – DevZer0

+0

Загрузка 2-гигабайтного avi-файла - единственный способ узнать, что это 'Content-type' is' video/avi'? На самом деле, нет. – zuza

Смежные вопросы