Najlepsze, co mogłem znaleźć, to if
fclose
fopen
typ, sprawia, że strona ładuje się bardzo wolno.
Zasadniczo próbuję wykonać następujące czynności: Mam listę witryn internetowych i chcę wyświetlić obok nich ich ikony ulubionych. Jeśli jednak witryna go nie ma, wolę zastąpić ją innym obrazem, zamiast wyświetlać uszkodzony obraz.
onerror
obrazu, np rozwiązanie przy użyciu jQueryOdpowiedzi:
Możesz poinstruować curl, aby używał metody HTTP HEAD za pośrednictwem CURLOPT_NOBODY.
Mniej więcej
$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);
W każdym razie oszczędzasz tylko koszt transferu HTTP, a nie ustanowienie i zamknięcie połączenia TCP. Ponieważ ikony ulubionych są małe, możesz nie zauważyć dużej poprawy.
Lokalne buforowanie wyniku wydaje się dobrym pomysłem, jeśli okaże się, że jest zbyt wolne. HEAD sprawdza czas pliku i zwraca go w nagłówkach. Możesz lubić przeglądarki i uzyskać CURLINFO_FILETIME ikony. W swojej pamięci podręcznej możesz przechowywać URL => [favicon, timestamp]. Następnie możesz porównać sygnaturę czasową i ponownie załadować ikonę ulubionych.
źródło
retcode
błędy na wszystkich 400 kodach, więc walidacja byłaby>=
nie tylko>
Jak mówi Pies, możesz użyć cURL. Możesz uzyskać cURL, aby podawał tylko nagłówki, a nie treść, co może przyspieszyć. Zła domena zawsze może zająć trochę czasu, ponieważ będziesz czekać na przekroczenie limitu czasu żądania; prawdopodobnie możesz zmienić limit czasu za pomocą cURL.
Oto przykład:
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'; }
źródło
Rozwiązanie CoolGoose jest dobre, ale jest szybsze w przypadku dużych plików (ponieważ próbuje odczytać tylko 1 bajt):
if (false === file_get_contents("http://example.com/path/to/image",0,null,0,1)) { $image = $default_image; }
źródło
fopen
- jeśli kod powrotu żądania to 404, fopen zwraca false.To nie jest odpowiedź na Twoje pierwotne pytanie, ale lepszy sposób na zrobienie tego, co próbujesz zrobić:
Zamiast bezpośrednio próbować uzyskać favicon witryny (co jest królewskim problemem, biorąc pod uwagę, że może to być /favicon.png, /favicon.ico, /favicon.gif lub nawet /path/to/favicon.png), użyj google:
<img src="http://www.google.com/s2/favicons?domain=[domain]">
Gotowe.
źródło
Pełna funkcja najczęściej głosowanej odpowiedzi:
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;} }
Możesz go używać w ten sposób:
if(remote_file_exists($url)) { //file exists, do something }
źródło
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
. Zaktualizowałem odpowiedź, aby obsługiwać302
przekierowania.Jeśli masz do czynienia z obrazami, użyj getimagesize. W przeciwieństwie do file_exists, ta wbudowana funkcja obsługuje zdalne pliki. Zwróci tablicę zawierającą informacje o obrazie (szerokość, wysokość, typ… itd.). Wszystko co musisz zrobić to sprawdzić pierwszy element tablicy (szerokość). użyj print_r do wyprowadzenia zawartości tablicy
$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"; }
źródło
@
przedgetimagesize
, ale czując się winny za ten hack.exif_imagetype
i jest to znacznie szybsze stackoverflow.com/a/38295345/1250044Można to zrobić, uzyskując kod stanu HTTP (404 = nie znaleziono), co jest możliwe w przypadku
file_get_contents
Dokumentów korzystających z opcji kontekstu. Poniższy kod bierze pod uwagę przekierowania i zwraca kod statusu miejsca docelowego ( 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";
Jeśli nie chcesz podążać za przekierowaniami, możesz to zrobić podobnie ( 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";
Niektóre z używanych funkcji, opcji i zmiennych są bardziej szczegółowo wyjaśnione w poście na blogu, który napisałem: HEAD najpierw ze strumieniami PHP .
źródło
$http_response_header
zobacz php.net/manual/en/reserved.variables.httpresponseheader.php .if (false === file_get_contents("http://example.com/path/to/image")) { $image = $default_image; }
Powinno działać ;)
źródło
Wbudowane funkcje PHP mogą nie działać do sprawdzania adresu URL, jeśli ustawienie allow_url_fopen jest wyłączone ze względów bezpieczeństwa. Curl to lepsza opcja, ponieważ nie musielibyśmy zmieniać naszego kodu na późniejszym etapie. Poniżej znajduje się kod, którego użyłem do zweryfikowania prawidłowego adresu 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; }
Zwróć uwagę na opcję CURLOPT_SSL_VERIFYPEER , która również weryfikuje adresy URL zaczynające się od HTTPS.
źródło
Aby sprawdzić istnienie obrazów,
exif_imagetype
powinno być preferowanegetimagesize
, ponieważ jest znacznie szybsze.Aby pominąć
E_NOTICE
, po prostu dodaj przed operatorem kontroli błędów (@
).if (@exif_imagetype($filename)) { // Image exist }
Jako bonus, zwracając wartość (
IMAGETYPE_XXX
) z,exif_imagetype
możemy również uzyskać typ MIME lub rozszerzenie pliku za pomocąimage_type_to_mime_type
/image_type_to_extension
.źródło
Radykalnym rozwiązaniem byłoby wyświetlenie ikon ulubionych jako obrazów tła w div nad domyślną ikoną. W ten sposób cały narzut zostanie umieszczony na kliencie, a nadal nie będą wyświetlać uszkodzonych obrazów (brakujące obrazy tła są ignorowane we wszystkich przeglądarkach AFAIK).
źródło
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!!!"; }
źródło
Możesz użyć następujących:
$file = 'http://mysite.co.za/images/favicon.ico'; $file_exists = (@fopen($file, "r")) ? true : false;
U mnie zadziałało, gdy próbowałem sprawdzić, czy pod adresem URL istnieje obraz
źródło
Możesz użyć :
$url=getimagesize(“http://www.flickr.com/photos/27505599@N07/2564389539/”); if(!is_array($url)) { $default_image =”…/directoryFolder/junal.jpg”; }
źródło
To działa dla mnie, aby sprawdzić, czy zdalny plik istnieje w 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'; }
źródło
Powinieneś wysyłać żądania HEAD, a nie GET, ponieważ w ogóle nie potrzebujesz zawartości URI. Jak powiedział Pies powyżej, powinieneś sprawdzić kod statusu (w zakresach 200-299 i opcjonalnie możesz śledzić przekierowania 3xx).
Odpowiedzi zawierają wiele przykładów kodu, które mogą być pomocne: PHP / Curl: HEAD Żądanie zajmuje dużo czasu w niektórych witrynach
źródło
Jest jeszcze bardziej wyrafinowana alternatywa. Możesz sprawdzić wszystko po stronie klienta, używając sztuczki 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); }; });
Z http://snipplr.com/view/18782/add-a-favicon-near-external-links-with-jquery/ (oryginalny blog jest obecnie niedostępny)
źródło
wszystkie odpowiedzi tutaj, które używają get_headers (), wykonują żądanie GET. O wiele szybciej / taniej jest po prostu wykonać żądanie HEAD.
Aby upewnić się, że get_headers () wykonuje żądanie HEAD zamiast GET, należy dodać to:
stream_context_set_default( array( 'http' => array( 'method' => 'HEAD' ) ) );
aby sprawdzić, czy plik istnieje, Twój kod będzie wyglądał mniej więcej tak:
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 oczywiście zwróci wartość false lub true.
źródło
Nie wiem, czy ten jest szybszy, gdy plik nie istnieje zdalnie, is_file () , ale możesz spróbować.
$favIcon = 'default FavIcon'; if(is_file($remotePath)) { $favIcon = file_get_contents($remotePath); }
źródło
var_dump(is_file('http://cdn.sstatic.net/stackoverflow/img/sprites.png')); bool(false)
Jeśli plik nie jest hostowany na zewnątrz, możesz przetłumaczyć zdalny adres URL na bezwzględną ścieżkę na serwerze WWW. W ten sposób nie musisz wywoływać CURL ani file_get_contents itp.
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' );
źródło
Jeśli używasz frameworka Symfony, istnieje również znacznie prostszy sposób użycia
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; }
Dokumentacja dla HttpClient jest również bardzo dobra i być może warto się jej przyjrzeć, jeśli potrzebujesz bardziej szczegółowego podejścia: https://symfony.com/doc/current/http_client.html
źródło
Możesz użyć systemu plików: użyj Symfony \ Component \ Filesystem \ Filesystem; użyj Symfony \ Component \ Filesystem \ Exception \ IOExceptionInterface;
i sprawdź $ fileSystem = new Filesystem (); if ($ fileSystem-> exist ('path_to_file') == true) {...
źródło