O melhor que pude encontrar, um if
fclose
fopen
tipo de coisa, faz a página carregar bem devagar.
Basicamente, o que estou tentando fazer é o seguinte: tenho uma lista de sites e desejo exibir seus favicons ao lado deles. No entanto, se um site não tiver um, gostaria de substituí-lo por outra imagem em vez de exibir uma imagem corrompida.
onerror
imagem, por exemplo, uma solução usando jQueryRespostas:
Você pode instruir o curl a usar o método HTTP HEAD via CURLOPT_NOBODY.
Mais ou menos
$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 qualquer forma, você economiza apenas no custo da transferência HTTP, não no estabelecimento e fechamento da conexão TCP. E sendo favicons pequenos, você pode não ver muitas melhorias.
Armazenar o resultado localmente em cache parece uma boa ideia se ficar muito lento. HEAD verifica a hora do arquivo e a retorna nos cabeçalhos. Você pode fazer como navegadores e obter o CURLINFO_FILETIME do ícone. Em seu cache, você pode armazenar o URL => [favicon, timestamp]. Você pode então comparar o carimbo de data / hora e recarregar o favicon.
fonte
retcode
erros em todos os 400 códigos para que a validação não fosse>=
justa>
Como Pies dizem, você pode usar cURL. Você pode fazer com que o cURL forneça apenas os cabeçalhos, e não o corpo, o que pode torná-lo mais rápido. Um domínio inválido sempre pode demorar um pouco porque você estará aguardando o tempo limite da solicitação expirar; você provavelmente poderia alterar a duração do tempo limite usando cURL.
Aqui está um exemplo:
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'; }
fonte
A solução do CoolGoose é boa, mas é mais rápida para arquivos grandes (pois tenta ler apenas 1 byte):
if (false === file_get_contents("http://example.com/path/to/image",0,null,0,1)) { $image = $default_image; }
fonte
fopen
- se o código de retorno da solicitação for 404, fopen retornará falso.Esta não é uma resposta à sua pergunta original, mas uma maneira melhor de fazer o que você está tentando fazer:
Em vez de tentar obter o favicon do site diretamente (o que é uma pena, pois pode ser /favicon.png, /favicon.ico, /favicon.gif ou mesmo /path/to/favicon.png), use o google:
<img src="http://www.google.com/s2/favicons?domain=[domain]">
Feito.
fonte
Uma função completa da resposta mais votada:
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;} }
Você pode usá-lo assim:
if(remote_file_exists($url)) { //file exists, do something }
fonte
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
. Eu atualizei a resposta para lidar com302
redirecionamentos.Se você estiver lidando com imagens, use getimagesize. Ao contrário de file_exists, esta função integrada oferece suporte a arquivos remotos. Ele retornará um array que contém as informações da imagem (largura, altura, tipo ... etc). Tudo que você precisa fazer é verificar o primeiro elemento do array (a largura). use print_r para produzir o conteúdo do array
$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"; }
fonte
@
na frente degetimagesize
, mas me sentindo culpado por esse hack.exif_imagetype
, e é muito mais rápido stackoverflow.com/a/38295345/1250044Isso pode ser feito obtendo o código de status HTTP (404 = não encontrado), que é possível com o
file_get_contents
Docs usando opções de contexto. O código a seguir leva os redirecionamentos em consideração e retornará o código de status do destino final ( 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";
Se não quiser seguir redirecionamentos, você pode fazer isso de forma semelhante ( 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";
Algumas das funções, opções e variáveis em uso são explicadas com mais detalhes em uma postagem de blog que escrevi: HEAD first with PHP Streams .
fonte
$http_response_header
consulte php.net/manual/en/reserved.variables.httpresponseheader.php .if (false === file_get_contents("http://example.com/path/to/image")) { $image = $default_image; }
Deveria trabalhar ;)
fonte
As funções embutidas do PHP podem não funcionar para verificar a URL se a configuração allow_url_fopen estiver desligada por razões de segurança. Curl é uma opção melhor, pois não precisaríamos alterar nosso código em um estágio posterior. Abaixo está o código que usei para verificar um URL válido:
$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; }
Observe a opção CURLOPT_SSL_VERIFYPEER, que também verifica se o URL começa com HTTPS.
fonte
Para verificar a existência de imagens,
exif_imagetype
deve-se preferirgetimagesize
, pois é muito mais rápido.Para suprimir o
E_NOTICE
, basta acrescentar o operador de controle de erro (@
).if (@exif_imagetype($filename)) { // Image exist }
Como um bônus, com o valor retornado (
IMAGETYPE_XXX
) deexif_imagetype
também podemos obter o tipo MIME ou a extensão de arquivo comimage_type_to_mime_type
/image_type_to_extension
.fonte
Uma solução radical seria exibir os favicons como imagens de fundo em um div acima do ícone padrão. Dessa forma, toda a sobrecarga seria colocada no cliente, embora ainda não exibisse imagens quebradas (imagens de fundo ausentes são ignoradas em todos os navegadores AFAIK).
fonte
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!!!"; }
fonte
Você pode usar o seguinte:
$file = 'http://mysite.co.za/images/favicon.ico'; $file_exists = (@fopen($file, "r")) ? true : false;
Funcionou para mim ao tentar verificar se existe uma imagem no URL
fonte
Você pode usar :
$url=getimagesize(“http://www.flickr.com/photos/27505599@N07/2564389539/”); if(!is_array($url)) { $default_image =”…/directoryFolder/junal.jpg”; }
fonte
Isso funciona para mim para verificar se existe um arquivo remoto no 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'; }
fonte
Você deve emitir solicitações HEAD, não GET, porque você não precisa do conteúdo URI de forma alguma. Como Pies disse acima, você deve verificar o código de status (em intervalos de 200-299, e você pode opcionalmente seguir redirecionamentos 3xx).
A questão das respostas contém muitos exemplos de código que podem ser úteis: PHP / Curl: Solicitação HEAD demora muito em alguns sites
fonte
Existe uma alternativa ainda mais sofisticada. Você pode fazer a verificação de todo o lado do cliente usando um truque 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); }; });
De http://snipplr.com/view/18782/add-a-favicon-near-external-links-with-jquery/ (o blog original está atualmente fora do ar)
fonte
todas as respostas aqui que usam get_headers () estão fazendo uma solicitação GET. É muito mais rápido / mais barato apenas fazer uma solicitação HEAD.
Para garantir que get_headers () faça uma solicitação HEAD em vez de GET, você deve adicionar isto:
stream_context_set_default( array( 'http' => array( 'method' => 'HEAD' ) ) );
então, para verificar se existe um arquivo, seu código seria semelhante a este:
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 retornará falso ou verdadeiro, obviamente.
fonte
Não sei se este é mais rápido quando o arquivo não existe remotamente, is_file () , mas você pode tentar.
$favIcon = 'default FavIcon'; if(is_file($remotePath)) { $favIcon = file_get_contents($remotePath); }
fonte
var_dump(is_file('http://cdn.sstatic.net/stackoverflow/img/sprites.png')); bool(false)
Se o arquivo não estiver hospedado externamente, você pode traduzir o URL remoto em um caminho absoluto em seu servidor da web. Dessa forma, você não precisa chamar CURL ou file_get_contents, etc.
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' );
fonte
Se você estiver usando o framework Symfony, também há uma maneira muito mais simples de usar
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; }
Os documentos para o HttpClient também são muito bons e talvez valha a pena dar uma olhada se você precisar de uma abordagem mais específica: https://symfony.com/doc/current/http_client.html
fonte
Você pode usar o sistema de arquivos: use Symfony \ Component \ Filesystem \ Filesystem; use Symfony \ Component \ Filesystem \ Exception \ IOExceptionInterface;
e verifique $ fileSystem = new Filesystem (); if ($ fileSystem-> exists ('path_to_file') == true) {...
fonte