Comment vérifier si un fichier distant existe en utilisant PHP?

le meilleur que j'ai pu trouver, un if fclose fopen chose de type, rend le chargement de la page vraiment lentement.

fondamentalement, ce que j'essaie de faire est la suivante: j'ai une liste de sites Web, et je veux afficher leurs favicons à côté d'eux. Cependant, si un site n'en a pas, j'aimerais le remplacer par une autre image plutôt que d'afficher une image brisée.

72
demandé sur Ramon Poca 2009-06-11 19:52:39

19 réponses

vous pouvez demander à curl d'utiliser la méthode HTTP HEAD via CURLOPT_NOBODY.

plus ou moins

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

de toute façon, vous économisez seulement le coût du transfert HTTP, pas l'établissement de connexion TCP et la fermeture. Et comme les favicons sont petits, vous ne verrez peut-être pas beaucoup d'amélioration.

Cacher le résultat localement semble une bonne idée s'il s'avère être trop lent. TÊTE vérifie l'heure du fichier, et retourne dans le tête. Vous pouvez faire comme les navigateurs et obtenir le CURLINFO_FILETIME de l'icône. Dans votre cache, vous pouvez stocker L'URL => [ favicon, timestamp ]. Vous pouvez alors comparer l'horodatage et recharger le favicon.

122
répondu Ramon Poca 2013-10-14 14:42:32

comme disent les tartes, vous pouvez utiliser cURL. Vous pouvez obtenir cURL pour seulement vous donner les headers, et pas le corps, ce qui pourrait le rendre plus rapide. Un mauvais domaine peut toujours prendre un certain temps parce que vous attendrez la requête pour time-out; vous pouvez probablement changer la durée de timeout en utilisant cURL.

voici un exemple:

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';   
}
57
répondu Tom Haigh 2009-06-11 16:20:08

la solution de CoolGoose est bonne mais elle est plus rapide pour les gros fichiers (car elle ne tente de lire qu'un octet):

if (false === file_get_contents("http://example.com/path/to/image",0,null,0,1)) {
    $image = $default_image;
}
30
répondu luBar 2010-04-27 22:58:07

ce n'est pas une réponse à votre question initiale, mais une meilleure façon de faire ce que vous essayez de faire:

au lieu de réellement essayer d'obtenir le favicon du site directement (qui est une douleur royale étant donné qu'il pourrait être /favicon.png, / favicon.ico, / favicon.gif, ou même /chemin/vers/favicon.png), utilisez google:

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

fait.

25
répondu Mala 2010-05-16 09:10:21

si vous avez affaire à des images, utilisez getimagesize. Contrairement à file_exists, cette fonction intégrée supporte les fichiers distants. Elle retourne un tableau qui contient les informations de l'image (largeur, hauteur, type..etc.) Tout ce que vous avez à faire est de vérifier le premier élément du tableau (la largeur). utilisez print_r pour afficher le contenu du tableau

$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";
}
18
répondu Эџad Дьdulяңмaи 2012-05-04 09:22:14

une fonction complète de la réponse la plus votée:

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

Vous pouvez l'utiliser comme ceci:

if(remote_file_exists($url))
{
    //file exists, do something
}
11
répondu Pedro Lobito 2018-05-02 17:43:11

cela peut être fait en obtenant le code D'état HTTP (404 = not found) qui est possible avec file_get_contents Docs faisant usage d'options de contexte. Le code suivant prend en compte les redirections et renvoie le code d'état de la destination finale ( 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";

Si vous ne voulez pas suivre les redirections, vous pouvez le faire similaire ( Démo ):

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

certaines des fonctions, options et variables utilisées sont expliquées plus en détail sur un billet de blog que j'ai écrit: HEAD first with PHP Streams .

7
répondu hakre 2011-09-17 16:43:38
if (false === file_get_contents("http://example.com/path/to/image")) {
    $image = $default_image;
}

Devrait fonctionner ;)

6
répondu CoolGoose 2009-06-11 16:02:21

les fonctions intégrées de PHP peuvent ne pas fonctionner pour vérifier L'URL si le paramètre allow_url_fopen est désactivé pour des raisons de sécurité. Curl est une meilleure option car nous n'aurions pas besoin de changer notre code à un stade ultérieur. Voici le code que j'ai utilisé pour vérifier une URL valide:

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

Veuillez noter l'option CURLOPT_SSL_VERIFYPEER qui vérifie également les URL commençant par HTTPS.

5
répondu Krishan Gopal 2014-04-23 10:02:33

une solution radicale serait d'afficher les favicons comme images de fond dans un div au-dessus de votre icône par défaut. De cette façon, tous les frais généraux seraient placés sur le client tout en n'affichant pas les images cassées (les images de fond manquantes sont ignorées dans tous les navigateurs AFAIK).

4
répondu truppo 2009-06-11 16:17:22
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
répondu dr.linux 2012-02-09 01:22:08

vous pouvez utiliser ce qui suit:

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

a fonctionné pour moi en essayant de vérifier si une image existe sur L'URL

3
répondu Rickus Harmse 2016-05-24 07:09:31

vous pouvez utiliser:

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

if(!is_array($url))
{
   $default_image =”…/directoryFolder/junal.jpg”;
}
2
répondu CP Soni 2012-06-08 04:36:07

vous devriez émettre des requêtes principales, pas en obtenir une, parce que vous n'avez pas besoin du tout du contenu URI. Comme Pies dit ci-dessus, vous devriez vérifier le code d'état (dans les gammes 200-299, et vous pouvez éventuellement suivre 3xx redirects).

Les réponses à la question contiennent beaucoup d'exemples de code qui peut être utile: PHP / Curl: TÊTE de Demande prend du temps sur certains sites

1
répondu drdaeman 2017-05-23 11:54:58

il y a une alternative encore plus sophistiquée. Vous pouvez vérifier tous les côté client en utilisant un tour de 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:\/\/[^\/]+).*$/, '')+'/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); };
});

à Partir de http://snipplr.com/view/18782/add-a-favicon-near-external-links-with-jquery/ (à l'origine, le blog est actuellement en bas)

1
répondu S Pangborn 2009-09-11 20:25:24

toutes les réponses qui utilisent get_headers() font une requête GET. Il est beaucoup plus rapide/moins cher de simplement faire une demande de tête.

pour vous assurer que get_headers() effectue une requête HEAD au lieu d'une GET, vous devez ajouter ceci:

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

donc pour vérifier si un fichier existe, votre code ressemblerait à quelque chose comme ceci:

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 retournera soit false soit true, évidemment.

1
répondu Ludo - Off the record 2015-03-01 00:58:56

pour vérifier l'existence d'images, exif_imagetype devrait être préféré à getimagesize , comme il est beaucoup plus rapide.

pour supprimer la E_NOTICE , il suffit de préparer l'opérateur de contrôle des erreurs ( @ ).

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

comme bonus, avec la valeur retournée ( IMAGETYPE_XXX ) de exif_imagetype nous pourrions aussi obtenir le type mime ou l'extension de fichier avec image_type_to_mime_type / image_type_to_extension .

1
répondu yckart 2016-07-10 19:12:09

cela fonctionne pour moi de vérifier si un fichier distant existe en 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
répondu user7018984 2017-12-21 08:03:34

Je ne sais pas si celui-ci est plus rapide quand le fichier n'existe pas à distance, is_file () , mais vous pouvez lui donner une chance.

$favIcon = 'default FavIcon';
if(is_file($remotePath)) {
   $favIcon = file_get_contents($remotePath);
}
0
répondu PatrikAkerstrand 2009-06-11 16:09:06