it-swarm.com.de

Wie kann man mit PHP überprüfen, ob eine entfernte Datei existiert?

Das Beste, was ich finden konnte, ein Ding vom Typ iffclosefopen, bewirkt, dass die Seite sehr langsam geladen wird.

Grundsätzlich versuche ich Folgendes: Ich habe eine Liste von Websites und möchte deren Favoriten daneben anzeigen. Wenn eine Site jedoch keine hat, möchte ich sie durch ein anderes Bild ersetzen, anstatt ein fehlerhaftes Bild anzuzeigen.

83
Oliver

Sie können curl anweisen, die HTTP-Methode HEAD über CURLOPT_NOBODY zu verwenden.

Mehr oder weniger

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

Auf jeden Fall sparen Sie nur die Kosten für die HTTP-Übertragung, nicht für den Aufbau und das Schließen der TCP) - Verbindung. Da die Favoriten klein sind, werden Sie möglicherweise keine große Verbesserung feststellen.

Das Ergebnis lokal zwischenzuspeichern scheint eine gute Idee zu sein, wenn es sich als zu langsam herausstellt. HEAD prüft die Uhrzeit der Datei und gibt sie in den Headern zurück. Sie können wie bei Browsern die CURLINFO_FILETIME des Symbols abrufen. In Ihrem Cache können Sie die URL speichern => [favicon, timestamp]. Anschließend können Sie den Zeitstempel vergleichen und das Favicon neu laden.

131
Ramon Poca

Wie Pasteten sagen, können Sie CURL verwenden. Sie können cURL so einstellen, dass nur die Header und nicht der Body angezeigt werden, wodurch der Vorgang möglicherweise beschleunigt wird. Eine fehlerhafte Domain kann immer eine Weile dauern, da Sie auf eine Zeitüberschreitung der Anforderung warten. Sie könnten wahrscheinlich die Timeout-Länge mit cURL ändern.

Hier ist ein Beispiel:

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';   
}
60
Tom Haigh

Die Lösung von CoolGoose ist gut, aber dies ist schneller für große Dateien (da nur versucht wird, 1 Byte zu lesen):

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

Dies ist keine Antwort auf Ihre ursprüngliche Frage, sondern eine bessere Möglichkeit, das zu tun, was Sie versuchen:

Anstatt tatsächlich zu versuchen, das Favicon der Site direkt abzurufen (was angesichts der Tatsache, dass es sich um /favicon.png, /favicon.ico, /favicon.gif oder sogar /path/to/favicon.png handeln könnte, ein königlicher Schmerz ist), verwenden Sie google:

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

Getan.

27
Mala

Wenn Sie mit Bildern arbeiten, verwenden Sie getimagesize. Im Gegensatz zu file_exists unterstützt diese integrierte Funktion Remotedateien. Es wird ein Array zurückgegeben, das die Bildinformationen enthält (Breite, Höhe, Typ..etc). Alles, was Sie tun müssen, ist das erste Element im Array (die Breite) zu überprüfen. Verwenden Sie print_r, um den Inhalt des Arrays auszugeben

$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";
}

Eine vollständige Funktion der am häufigsten gewählten Antwort:

function remote_file_exists($url)
{
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_NOBODY, true);
    curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    if( $httpCode == 200 ){return true;}
}

Du kannst es so benutzen:

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

Dies kann durch Abrufen des HTTP-Statuscodes (404 = nicht gefunden) erreicht werden, der mit file_get_contents Text & Tabellen Kontextoptionen nutzen. Der folgende Code berücksichtigt Weiterleitungen und gibt den Statuscode des endgültigen Ziels zurück ( 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";

Wenn Sie Weiterleitungen nicht folgen möchten, können Sie dies auf ähnliche Weise tun ( Demo ):

$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";

Einige der Funktionen, Optionen und Variablen, die verwendet werden, werden in einem Blog-Beitrag, den ich geschrieben habe, ausführlicher erläutert: HEAD first with PHP Streams .

7
hakre

PHPs eingebaute Funktionen funktionieren möglicherweise nicht zum Überprüfen von URLs, wenn allow_url_fopen aus Sicherheitsgründen deaktiviert ist. Curl ist eine bessere Option da wir unseren Code später nicht mehr ändern müssten. Unten ist der Code, mit dem ich eine gültige URL überprüft habe:

$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; } 

Beachten Sie bitte die Option CURLOPT_SSL_VERIFYPEER, mit der auch die URLs überprüft werden, die mit HTTPS beginnen.

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

Sollte arbeiten ;)

6
CoolGoose

Eine radikale Lösung wäre, die Favoriten als Hintergrundbilder in einem Div über Ihrem Standardsymbol anzuzeigen. Auf diese Weise wird der gesamte Overhead auf dem Client abgelegt, ohne dass fehlerhafte Bilder angezeigt werden (fehlende Hintergrundbilder werden in allen AFAIK-Browsern ignoriert).

4
truppo

Um die Existenz von Bildern zu überprüfen, sollte exif_imagetype gegenüber getimagesize bevorzugt werden, da dies viel schneller ist.

Um den E_NOTICE zu unterdrücken, stellen Sie einfach den Fehlerüberwachungsoperator (@) Voran.

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

Als Bonus können wir mit dem zurückgegebenen Wert (IMAGETYPE_XXX) Von exif_imagetype Auch den MIME-Typ oder die Dateierweiterung mit image_type_to_mime_type/image_type_to_extension Erhalten.

3
yckart

Sie könnten Folgendes verwenden:

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

Arbeitete für mich beim Versuch zu überprüfen, ob ein Bild in der URL vorhanden ist

3
Rickus Harmse
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
dr.linux

Sie können verwenden:

$url=getimagesize(“http://www.flickr.com/photos/[email protected]/2564389539/”);

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

Sie sollten HEAD - Anforderungen absetzen, keine abrufen, da Sie den URI-Inhalt überhaupt nicht benötigen Sie können optional 3xx Weiterleitungen folgen.

Die Antwortfrage enthält viele Codebeispiele, die hilfreich sein können: PHP/Curl: HEAD Anfrage dauert auf einigen Websites sehr lange

1
drdaeman

Dies funktioniert für mich, um zu überprüfen, ob eine entfernte Datei in PHP existiert:

$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
user7018984

alle Antworten hier, die get_headers () verwenden, führen eine GET-Anforderung aus. Es ist viel schneller/billiger, nur eine HEAD Anfrage zu machen.

Um sicherzustellen, dass get_headers () eine HEAD) -Anforderung anstelle eines GET ausführt, sollten Sie Folgendes hinzufügen:

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

um zu überprüfen, ob eine Datei existiert, würde Ihr Code ungefähr so ​​aussehen:

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 gibt offensichtlich entweder false oder true zurück.

Es gibt eine noch raffiniertere Alternative. Sie können die Überprüfung auf allen Clients mithilfe eines JQuery-Tricks durchführen.

$('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); };
});

Von http://snipplr.com/view/18782/add-a-favicon-near-external-links-with-jquery/ (das ursprüngliche Blog ist derzeit inaktiv)

1
S Pangborn

Wenn die Datei nicht extern gehostet wird, können Sie die entfernte URL in einen absoluten Pfad auf Ihrem Webserver übersetzen. Auf diese Weise müssen Sie nicht CURL oder file_get_contents usw. aufrufen.

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

Hinweis: Ihr Webserver muss DOCUMENT_ROOT ausfüllen, um diese Funktion verwenden zu können

0

Ich weiß nicht, ob dieser schneller ist, wenn die Datei nicht remote vorhanden ist, is_file () , aber Sie könnten es versuchen.

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