2010-12-05 2 views
55

Я использую file_get_contents() для доступа к URL-адресу.file_get_contents, когда url не существует

file_get_contents('http://somenotrealurl.com/notrealpage'); 

Если URL-адрес не является реальным, он возвращает это сообщение об ошибке. Как я могу получить его с ошибкой изящно, чтобы я знал, что страница не существует и действует соответственно без отображения этого сообщения об ошибке?

file_get_contents('http://somenotrealurl.com/notrealpage') 
[function.file-get-contents]: 
failed to open stream: HTTP request failed! HTTP/1.0 404 Not Found 
in myphppage.php on line 3 

, например, в Зенд вы можете сказать: if ($request->isSuccessful())

$client = New Zend_Http_Client(); 
$client->setUri('http://someurl.com/somepage'); 

$request = $client->request(); 

if ($request->isSuccessful()) { 
//do stuff with the result 
} 
+0

попробуйте использовать контекст потока: http://stackoverflow.com/questions/21800276/is-it-possible-to-get-404-page-content-using-fopen-in-php, file_get_contents использует FOPEN под капотом. – rsk82 2014-02-15 19:24:58

ответ

87

Вам нужно проверить HTTP response code:

function get_http_response_code($url) { 
    $headers = get_headers($url); 
    return substr($headers[0], 9, 3); 
} 
if(get_http_response_code('http://somenotrealurl.com/notrealpage') != "200"){ 
    echo "error"; 
}else{ 
    file_get_contents('http://somenotrealurl.com/notrealpage'); 
} 
46

С такими командами в PHP, вы можете префикс их с @ для подавления таких предупреждений.

@file_get_contents('http://somenotrealurl.com/notrealpage'); 

file_get_contents() возвращается FALSE, если происходит сбой, так что если вы проверить возвращенный результат против этого, то вы можете справиться с Провал

$pageDocument = @file_get_contents('http://somenotrealurl.com/notrealpage'); 

if ($pageDocument === false) { 
    // Handle error 
} 
+3

Я не хочу просто подавлять ошибки. Я хочу знать, действителен ли URL. – sami 2010-12-05 09:22:39

+0

Обратите внимание, что если сервер не работает, функция может блокироваться некоторое время. – 2010-12-05 09:22:57

+0

@sami Когда вы говорите «действительный», вы имеете в виду действительный URL-адрес или «работает»? – Orbling 2010-12-05 09:25:47

13

Хотя file_get_contents очень тонкий и удобный, я предпочитаю библиотеку Curl для лучшего контроля. Вот пример.

function fetchUrl($uri) { 
    $handle = curl_init(); 

    curl_setopt($handle, CURLOPT_URL, $uri); 
    curl_setopt($handle, CURLOPT_POST, false); 
    curl_setopt($handle, CURLOPT_BINARYTRANSFER, false); 
    curl_setopt($handle, CURLOPT_HEADER, true); 
    curl_setopt($handle, CURLOPT_RETURNTRANSFER, true); 
    curl_setopt($handle, CURLOPT_CONNECTTIMEOUT, 10); 

    $response = curl_exec($handle); 
    $hlength = curl_getinfo($handle, CURLINFO_HEADER_SIZE); 
    $httpCode = curl_getinfo($handle, CURLINFO_HTTP_CODE); 
    $body  = substr($response, $hlength); 

    // If HTTP response is not 200, throw exception 
    if ($httpCode != 200) { 
     throw new Exception($httpCode); 
    } 

    return $body; 
} 

$url = 'http://some.host.com/path/to/doc'; 

try { 
    $response = fetchUrl($url); 
} catch (Exception $e) { 
    error_log('Fetch URL failed: ' . $e->getMessage() . ' for ' . $url); 
} 
22

Каждый раз, когда вы звоните file_get_contents с HTTP обертку, переменная в локальной области создается: $http_response_header

Эта переменная содержит все заголовки HTTP. Этот метод лучше, чем функция get_headers(), поскольку выполняется только один запрос.

Примечание: 2 разных запроса могут заканчиваться по-разному. Например, get_headers() вернет 503, а file_get_contents() вернет 200. И вы получите правильный вывод, но не будете использовать его из-за ошибки 503 в вызове get_headers().

function getUrl($url) { 
    $content = file_get_contents($url); 
    // you can add some code to extract/parse response number from first header. 
    // For example from "HTTP/1.1 200 OK" string. 
    return array(
      'headers' => $http_response_header, 
      'content' => $content 
     ); 
} 

// Handle 40x and 50x errors 
$response = getUrl("http://example.com/secret-message"); 
if ($response['content'] === FALSE) 
    echo $response['headers'][0]; // HTTP/1.1 401 Unauthorized 
else 
    echo $response['content']; 

Это также Alows Подход вы иметь отслеживать несколько заголовков запроса, хранящихся в различных переменных, так как если вы используете file_get_contents() $http_response_header переписывается в локальной области видимости.

3

Простой и функциональный (простой в использовании в любом месте):

function file_contents_exist($url, $response_code = 200) 
{ 
    $headers = get_headers($url); 

    if (substr($headers[0], 9, 3) == $response_code) 
    { 
     return TRUE; 
    } 
    else 
    { 
     return FALSE; 
    } 
} 

Пример:

$file_path = 'http://www.google.com'; 

if(file_contents_exist($file_path)) 
{ 
    $file = file_get_contents($file_path); 
} 
3

Чтобы избежать двойных запросов, как прокомментировал Orbling от ответа ynh вы могли бы объединить свои ответы , Если вы получите действительный ответ в первую очередь, используйте это. Если не узнать, в чем проблема (при необходимости).

$urlToGet = 'http://somenotrealurl.com/notrealpage'; 
$pageDocument = @file_get_contents($urlToGet); 
if ($pageDocument === false) { 
    $headers = get_headers($urlToGet); 
    $responseCode = substr($headers[0], 9, 3); 
    // Handle errors based on response code 
    if ($responseCode == '404') { 
     //do something, page is missing 
    } 
    // Etc. 
} else { 
    // Use $pageDocument, echo or whatever you are doing 
} 
Смежные вопросы