PHP를 사용하여 원격 파일이 존재하는지 어떻게 확인할 수 있습니까?


86

내가 찾을 수있는 최선의 if fclose fopen유형은 페이지로드를 정말 느리게 만듭니다.

기본적으로 내가하려는 것은 다음과 같습니다. 웹 사이트 목록이 있고 그 옆에 파비콘을 표시하고 싶습니다. 그러나 사이트에없는 경우 깨진 이미지를 표시하는 대신 다른 이미지로 교체하고 싶습니다.


CURL을 사용하여 반환 코드를 확인할 수 있다고 생각합니다. 그러나 속도가 문제라면 오프라인으로 캐시하고 캐시하십시오.
Michał Tatarynowicz

예,하지만 웹 사이트 목록을 구문 분석하고 파비콘이 있는지 확인하고 프런트 엔드 용으로 해당 데이터를 캐시하는 오프라인 스크립트 (cron에서 실행)를 사용하는 것이 좋습니다. 크론을 사용하지 않거나 사용할 수없는 경우 최소한 확인하는 모든 새 URL에 대한 결과를 캐시합니다.
Michał Tatarynowicz

3
브라우저에서 자리 이미지로 나누어 이미지 교체 친절 사용하여 클라이언트 측 솔루션을 고려 onerror이미지는 예 jQuery를 이용한 용액

답변:


135

curl에 CURLOPT_NOBODY를 통해 HTTP HEAD 메소드를 사용하도록 지시 할 수 있습니다.

다소간

$ch = curl_init("http://www.example.com/favicon.ico");

curl_setopt($ch, CURLOPT_NOBODY, true);
curl_exec($ch);
$retcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
// $retcode >= 400 -> not found, $retcode = 200, found.
curl_close($ch);

어쨌든 TCP 연결 설정 및 종료가 아닌 HTTP 전송 비용 만 절약됩니다. 그리고 파비콘이 작기 때문에 많은 개선을 보지 못할 수도 있습니다.

결과를 로컬로 캐싱하는 것이 너무 느린 것으로 판명되면 좋은 생각으로 보입니다. HEAD는 파일의 시간을 확인하고 헤더에 반환합니다. 당신은 브라우저처럼 할 수 있고 아이콘의 CURLINFO_FILETIME을 얻을 수 있습니다. 캐시에 URL => [favicon, timestamp]를 저장할 수 있습니다. 그런 다음 타임 스탬프를 비교하고 파비콘을 다시로드 할 수 있습니다.


6
단지 참고 사항 : retcode모든 400 개 코드에 오류가 검증 될 수 있도록 >=단지>
저스틴 불

4
일부 사이트는 사용자 에이전트 문자열을 제공하지 않으면 액세스를 차단 하므로이
rlorenzo

6
@Lyth 3XX retcode는 오류가 아니라 리디렉션입니다. 수동으로 처리하거나 CURLOPT_FOLLOWLOCATION을 사용하여 처리해야합니다.
Ramon Poca 2013 년

6
curl_setopt ($ ch, CURLOPT_SSL_VERIFYPEER, false)를 사용하십시오. HTTPS로 시작하는 URL에 대해 동일한 코드가 작동하는지 확인하십시오!
Krishan Gopal

61

Pies가 말했듯이 cURL을 사용할 수 있습니다. cURL을 사용하여 본문이 아닌 헤더 만 제공 할 수 있으므로 속도가 빨라질 수 있습니다. 잘못된 도메인은 요청이 시간 초과 될 때까지 기다리기 때문에 항상 시간이 걸릴 수 있습니다. cURL을 사용하여 시간 제한 길이를 변경할 수 있습니다.

예를 들면 다음과 같습니다.

function remoteFileExists($url) {
    $curl = curl_init($url);

    //don't fetch the actual page, you only want to check the connection is ok
    curl_setopt($curl, CURLOPT_NOBODY, true);

    //do request
    $result = curl_exec($curl);

    $ret = false;

    //if request did not fail
    if ($result !== false) {
        //if request was ok, check response code
        $statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);  

        if ($statusCode == 200) {
            $ret = true;   
        }
    }

    curl_close($curl);

    return $ret;
}

$exists = remoteFileExists('http://stackoverflow.com/favicon.ico');
if ($exists) {
    echo 'file exists';
} else {
    echo 'file does not exist';   
}

3
remoteFileExists ( ' stackoverflow.com/' ) 이것도 true를 반환하지만 링크 일뿐입니다. 확인하지 않는이 함수는 링크 콘텐츠 유형이 파일입니다.
Donatas Navidonskis

36

CoolGoose의 솔루션은 좋지만 대용량 파일의 경우 더 빠릅니다 (1 바이트 읽기만 시도하므로).

if (false === file_get_contents("http://example.com/path/to/image",0,null,0,1)) {
    $image = $default_image;
}

+1. CURL 솔루션에 대한이 솔루션의 단점은 무엇입니까?
Adriano Varoli Piazza

1
당신은 그냥 사용할 수 있습니다 fopen-요청 반환 코드가 404이면 fopen은 false를 반환합니다.
s3v3n 2011 년

이것은 정말 느리고 나를 위해 작동하지 않았습니다 (즉, 파일 경로가 정확하지 않은 경우에도 여전히 깨진 이미지를 표시 함을 의미합니다)
Helmut

이 방법은 이미지 나 파일이 없을 때마다 서버가 리디렉션하면 작동하지 않습니다. 이것은 사이트가 mod_rewrite 또는 요청을 처리하는 방식의 다른 "규칙"을 사용할 때 발생합니다.
Erik Čerpnjak

28

이것은 원래 질문에 대한 답이 아니지만 수행하려는 작업을 수행하는 더 나은 방법입니다.

실제로 사이트의 favicon을 직접 가져 오려고하는 대신 (/favicon.png, /favicon.ico, /favicon.gif 또는 /path/to/favicon.png 일 수 있다는 점을 감안하면 왕실의 고통입니다) google을 사용하세요.

<img src="http://www.google.com/s2/favicons?domain=[domain]">

끝난.


4
구문은 약간 혼란을 만듭니다. 예를 들면 다음과 같습니다. <img src = " google.com/s2/favicons?domain=stackoverflow.com ">
Habeeb Perwad

19

가장 많이 득표 한 답변의 완전한 기능 :

function remote_file_exists($url)
{
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_NOBODY, 1);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); # handles 301/2 redirects
    curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    if( $httpCode == 200 ){return true;}
}

다음과 같이 사용할 수 있습니다.

if(remote_file_exists($url))
{
    //file exists, do something
}

오! 나는 지난 이틀 동안 자리를 비 웠지만 월초는 거의 24 시간 연중 무휴였습니다. 알려 주셔서 감사합니다!
Pedro Lobito 2016 년

서버가 HTTP 코드에 응답하지 않는 경우 (또는 cUrl이이를 포착하지 못하는 경우) 작동하지 않습니다. 그것은 나에게 꽤 자주 발생합니다. 예 : 이미지의 경우.
Vaci 2019

URL이 다른 URL 또는 https 버전으로 리디렉션되면 어떻게됩니까? 이 경우이 컬 코드는 작업을 수행 할 수 없습니다. 가장 좋은 방법은 헤더 정보를 얻고 대소 문자를 구분하지 않는 문자열 "200 ok"를 검색하는 것입니다.
Infoconic

@Infoconic 추가 할 수 있습니다 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);. 302리디렉션 을 처리하기 위해 답변을 업데이트했습니다 .
Pedro Lobito

18

이미지를 다루는 경우 getimagesize를 사용하십시오. file_exists와 달리이 내장 함수는 원격 파일을 지원합니다. 이미지 정보 (너비, 높이, 유형 등)가 포함 된 배열을 반환합니다. 해야 할 일은 배열의 첫 번째 요소 (너비)를 확인하는 것입니다. print_r을 사용하여 배열의 내용을 출력하십시오.

$imageArray = getimagesize("http://www.example.com/image.jpg");
if($imageArray[0])
{
    echo "it's an image and here is the image's info<br>";
    print_r($imageArray);
}
else
{
    echo "invalid image";
}

원격 리소스를 사용할 수없는 경우 404 경고가 발생합니다. 당분간, 나는 사용하여 오류 억제하여 처리 @의 앞을 getimagesize하지만,이 해킹에 대한 죄책감.

제 경우에는 이미지 / 파일이 없을 때마다 리디렉션되기 때문에 이것이 최선의 방법이었습니다. 나는 두 번째로 @로 오류를 억제하는 것은 no go이지만이 경우에는 필요했습니다.
Erik Čerpnjak

를 사용할 수도 있다는 것을 알아 냈고 exif_imagetype훨씬 더 빠릅니다. stackoverflow.com/a/38295345/1250044
yckart

7

이는 file_get_contents문서 에서 컨텍스트 옵션을 사용하여 가능한 HTTP 상태 코드 (404 = 찾을 수 없음)를 가져 와서 수행 할 수 있습니다. 다음 코드는 리디렉션을 고려하고 최종 대상 ( Demo ) 의 상태 코드를 반환합니다 .

$url = 'http://example.com/';
$code = FALSE;

$options['http'] = array(
    'method' => "HEAD",
    'ignore_errors' => 1
);

$body = file_get_contents($url, NULL, stream_context_create($options));

foreach($http_response_header as $header)
    sscanf($header, 'HTTP/%*d.%*d %d', $code);

echo "Status code: $code";

리디렉션을 따르지 않으려면 다음과 같이 할 수 있습니다 ( 데모 ).

$url = 'http://example.com/';
$code = FALSE;

$options['http'] = array(
    'method' => "HEAD",
    'ignore_errors' => 1,
    'max_redirects' => 0
);

$body = file_get_contents($url, NULL, stream_context_create($options));

sscanf($http_response_header[0], 'HTTP/%*d.%*d %d', $code);

echo "Status code: $code";

사용중인 일부 함수, 옵션 및 변수는 내가 작성한 블로그 게시물에 자세히 설명되어 있습니다. HEAD first with PHP Streams .




PHP에 대한 자세한 내용 $http_response_headerphp.net/manual/en/reserved.variables.httpresponseheader.php를 참조하십시오 .
Big McLargeHuge 2014 년

1
두 번째 변형은 저에게 효과적이며 기본 file_get_contents 호출 (사용자 정의 stream_context 없음)과 비교하면 50 % 더 빠릅니다. 즉, 요청에 대해 3,4 초에서 1,7 초로 증가했습니다.
Erik Čerpnjak

@ ErikČerpnjak : "사용자 정의"stream_context가없는 경우 기본 컨텍스트입니다. 기본 컨텍스트에서 옵션을 가져 와서 사용자 정의 컨텍스트와 어떻게 다른지 살펴볼 수 있습니다. 이를 통해 타이밍이 다른 이유를 파악할 수 있습니다. - php.net/stream-context-get-defaultphp.net/stream-context-get-options
hakre

6
if (false === file_get_contents("http://example.com/path/to/image")) {
    $image = $default_image;
}

작동해야합니다;)


추가 @ 기능을하기 전에
Tebe

6

보안상의 이유로 allow_url_fopen 설정이 off로 설정된 경우 PHP의 내장 기능이 URL 확인에 작동하지 않을 수 있습니다 . Curl은 나중에 코드를 변경할 필요가 없기 때문에 더 나은 옵션입니다. 다음은 유효한 URL을 확인하는 데 사용한 코드입니다.

$url = str_replace(' ', '%20', $url);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_exec($ch);
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);  
curl_close($ch);
if($httpcode>=200 && $httpcode<300){  return true; } else { return false; } 

URL이 HTTPS로 시작하는지도 확인 하는 CURLOPT_SSL_VERIFYPEER 옵션을 참고 하십시오 .


6

이미지의 존재를 확인하려면을 (를 ) 훨씬 더 빠르기 때문에보다 exif_imagetype선호해야합니다 getimagesize.

을 표시하지 않으려면 E_NOTICE오류 제어 연산자 ( @)를 앞에 추가하십시오 .

if (@exif_imagetype($filename)) {
  // Image exist
}

보너스로 반환 된 값 ( IMAGETYPE_XXX)을 사용 exif_imagetype하여 image_type_to_mime_type/를 사용 하여 MIME 유형 또는 파일 확장자를 가져올 수도 있습니다 image_type_to_extension.


4

근본적인 해결책은 기본 아이콘 위의 div에 배경 이미지로 파비콘을 표시하는 것입니다. 이렇게하면 깨진 이미지를 표시하지 않는 동안 모든 오버 헤드가 클라이언트에 배치됩니다 (모든 브라우저 AFAIK에서 누락 된 배경 이미지는 무시 됨).


1
favicon (favicon.ico, favicon.gif, favicon.png)에 대해 여러 위치를 확인하지 않는 경우 +1이 최상의 솔루션 인 것 같습니다
Galen

3
function remote_file_exists($url){
   return(bool)preg_match('~HTTP/1\.\d\s+200\s+OK~', @current(get_headers($url)));
}  
$ff = "http://www.emeditor.com/pub/emed32_11.0.5.exe";
    if(remote_file_exists($ff)){
        echo "file exist!";
    }
    else{
        echo "file not exist!!!";
    }

3

다음을 사용할 수 있습니다.

$file = 'http://mysite.co.za/images/favicon.ico';
$file_exists = (@fopen($file, "r")) ? true : false;

URL에 이미지가 있는지 확인하려고 할 때 나를 위해 일했습니다.


2

당신이 사용할 수있는 :

$url=getimagesize(“http://www.flickr.com/photos/27505599@N07/2564389539/”);

if(!is_array($url))
{
   $default_image =”…/directoryFolder/junal.jpg”;
}

2

이것은 PHP에 원격 파일이 있는지 확인하는 데 효과적입니다.

$url = 'https://cdn.sstatic.net/Sites/stackoverflow/img/favicon.ico';
    $header_response = get_headers($url, 1);

    if ( strpos( $header_response[0], "404" ) !== false ) {
        echo 'File does NOT exist';
        } else {
        echo 'File exists';
        }

1

URI 내용이 전혀 필요하지 않기 때문에 GET 요청이 아닌 HEAD 요청을 발행해야합니다. Pies가 위에서 말했듯이 상태 코드를 확인해야합니다 (200-299 범위에서 선택적으로 3xx 리디렉션을 따를 수 있음).

답변 질문에는 도움이 될 수있는 많은 코드 예제가 포함되어 있습니다. PHP / Curl : 일부 사이트에서 HEAD 요청이 오래 걸립니다.


1

훨씬 더 정교한 대안이 있습니다. JQuery 트릭을 사용하여 모든 클라이언트 측을 확인할 수 있습니다.

$('a[href^="http://"]').filter(function(){
     return this.hostname && this.hostname !== location.hostname;
}).each(function() {
    var link = jQuery(this);
    var faviconURL =
      link.attr('href').replace(/^(http:\/\/[^\/]+).*$/, '$1')+'/favicon.ico';
    var faviconIMG = jQuery('<img src="favicon.png" alt="" />')['appendTo'](link);
    var extImg = new Image();
    extImg.src = faviconURL;
    if (extImg.complete)
      faviconIMG.attr('src', faviconURL);
    else
      extImg.onload = function() { faviconIMG.attr('src', faviconURL); };
});

에서 http://snipplr.com/view/18782/add-a-favicon-near-external-links-with-jquery/ (원래 블로그는 아래로 현재이다)


1

get_headers ()를 사용하는 모든 답변은 GET 요청을 수행합니다. HEAD 요청을 수행하는 것이 훨씬 빠르고 저렴합니다.

get_headers ()가 GET 대신 HEAD 요청을 수행하도록하려면 다음을 추가해야합니다.

stream_context_set_default(
    array(
        'http' => array(
            'method' => 'HEAD'
        )
    )
);

따라서 파일이 있는지 확인하려면 코드는 다음과 같습니다.

stream_context_set_default(
    array(
        'http' => array(
            'method' => 'HEAD'
        )
    )
);
$headers = get_headers('http://website.com/dir/file.jpg', 1);
$file_found = stristr($headers[0], '200');

$ file_found는 분명히 거짓 또는 참을 반환합니다.


0

파일이 원격으로 존재하지 않을 때 이것이 더 빠른지 모르겠지만, is_file ()은 시도해 볼 수 있습니다.

$favIcon = 'default FavIcon';
if(is_file($remotePath)) {
   $favIcon = file_get_contents($remotePath);
}

문서에서 : "PHP 5.0.0부터이 함수는 일부 URL 래퍼에서도 사용할 수 있습니다. 어떤 래퍼가 stat () 기능 군을 지원하는지 확인하려면 지원되는 프로토콜 및 래퍼를 참조하십시오."
PatrikAkerstrand 2010 년

스트림 래퍼를 등록하면 이것이 작동 할 수 있다는 뜻입니까? 작동하는 예를 보여주기 위해 질문을 편집하면 내 반대표를 제거하고 가능하면 찬성합니다. 그러나 지금은 원격 파일로 php cli에서 is_file을 테스트 한 결과 거짓이 발생했습니다.
greg0ire

어떤 작업 예 :var_dump(is_file('http://cdn.sstatic.net/stackoverflow/img/sprites.png')); bool(false)
greg0ire

0

파일이 외부에서 호스팅되지 않는 경우 원격 URL을 웹 서버의 절대 경로로 변환 할 수 있습니다. 이렇게하면 CURL 또는 file_get_contents 등을 호출 할 필요가 없습니다.

function remoteFileExists($url) {

    $root = realpath($_SERVER["DOCUMENT_ROOT"]);
    $urlParts = parse_url( $url );

    if ( !isset( $urlParts['path'] ) )
        return false;

    if ( is_file( $root . $urlParts['path'] ) )
        return true;
    else
        return false;

}

remoteFileExists( 'https://www.yourdomain.com/path/to/remote/image.png' );

참고 :이 기능을 사용하려면 웹 서버가 DOCUMENT_ROOT를 채워야합니다.


0

Symfony 프레임 워크를 사용하는 경우 다음을 사용하는 훨씬 더 간단한 방법도 있습니다 HttpClientInterface.

private function remoteFileExists(string $url, HttpClientInterface $client): bool {
    $response = $client->request(
        'GET',
        $url //e.g. http://example.com/file.txt
    );

    return $response->getStatusCode() == 200;
}

HttpClient에 대한 문서도 매우 훌륭하며보다 구체적인 접근 방식이 필요한 경우 살펴볼 가치가 있습니다. https://symfony.com/doc/current/http_client.html


-1

파일 시스템을 사용할 수 있습니다. use Symfony \ Component \ Filesystem \ Filesystem; Symfony \ Component \ Filesystem \ Exception \ IOExceptionInterface를 사용하십시오.

$ fileSystem = new Filesystem ();을 확인하십시오. if ($ fileSystem-> exists ( 'path_to_file') == true) {...

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.