Bagaimana seseorang dapat memeriksa untuk melihat apakah ada file jarak jauh menggunakan PHP?


87

Yang terbaik yang bisa saya temukan, if fclose fopenjenis hal, membuat halaman memuat sangat lambat.

Pada dasarnya apa yang saya coba lakukan adalah sebagai berikut: Saya memiliki daftar situs web, dan saya ingin menampilkan favicon mereka di sebelahnya. Namun, jika situs tidak memilikinya, saya ingin menggantinya dengan gambar lain daripada menampilkan gambar yang rusak.


Saya pikir Anda dapat menggunakan CURL dan memeriksa kode pengembaliannya. Tetapi jika kecepatan yang menjadi masalah, lakukan saja secara offline dan cache.
Michał Tatarynowicz

Ya, tetapi saya tetap akan merekomendasikan menggunakan skrip offline (dijalankan dari cron) yang mem-parsing daftar situs web, memeriksa apakah mereka memiliki favicon dan menyimpan data tersebut untuk frontend. Jika Anda tidak / tidak dapat menggunakan cron, setidaknya hasil cache untuk setiap URL baru yang Anda periksa.
Michał Tatarynowicz

3
Untuk mengganti gambar rusak dengan gambar placeholder di browser, pertimbangkan solusi sisi klien menggunakan onerrorgambar misalnya solusi menggunakan jQuery

Jawaban:


136

Anda dapat menginstruksikan curl untuk menggunakan metode HTTP HEAD melalui CURLOPT_NOBODY.

Lebih atau kurang

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

Bagaimanapun, Anda hanya menghemat biaya transfer HTTP, bukan pembuatan dan penutupan koneksi TCP. Dan karena favicon kecil, Anda mungkin tidak melihat banyak peningkatan.

Menyimpan hasil secara lokal tampaknya merupakan ide yang bagus jika ternyata terlalu lambat. HEAD memeriksa waktu file, dan mengembalikannya di header. Anda dapat melakukan seperti browser dan mendapatkan CURLINFO_FILETIME dari ikon. Di cache Anda, Anda dapat menyimpan URL => [favicon, timestamp]. Anda kemudian dapat membandingkan stempel waktu dan memuat ulang favicon.


6
hanya sebuah catatan: retcodekesalahan pada semua 400 kode sehingga validasinya >=tidak hanya>
Justin Bull

4
Beberapa situs memblokir akses jika Anda tidak memberikan user agent string, jadi saya sarankan mengikuti panduan ini untuk menambahkan CURLOPT_USERAGENT selain CURLOPT_NOBODY: davidwalsh.name/set-user-agent-php-curl-spoof
rlorenzo

6
@Lyth 3XX kode ulang bukanlah kesalahan, tapi pengalihan. Itu harus ditangani secara manual atau menggunakan CURLOPT_FOLLOWLOCATION.
Ramon Poca

6
Gunakan curl_setopt ($ ch, CURLOPT_SSL_VERIFYPEER, false); juga untuk memastikan kode yang sama berfungsi untuk URL yang dimulai dengan HTTPS!
Krishan Gopal

61

Seperti yang dikatakan Pies, Anda dapat menggunakan cURL. Anda bisa mendapatkan cURL untuk hanya memberi Anda header, dan bukan isi, yang mungkin membuatnya lebih cepat. Domain yang buruk selalu membutuhkan waktu beberapa saat karena Anda akan menunggu permintaan waktu habis; Anda mungkin dapat mengubah durasi waktu tunggu menggunakan cURL.

Berikut contohnya:

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/' ) ini juga akan mengembalikan nilai true, tetapi ini hanya tautan. Fungsi ini tidak memeriksa adalah jenis konten tautan adalah file.
Donatas Navidonskis

36

Solusi CoolGoose bagus tetapi ini lebih cepat untuk file besar (karena hanya mencoba membaca 1 byte):

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

+1. Apakah ada kekurangan dari solusi ini dibandingkan dengan CURL?
Adriano Varoli Piazza

1
Anda bisa menggunakan fopen- jika kode pengembalian permintaan adalah 404, fopen mengembalikan false.
s3v3n

ini sangat lambat dan tidak berhasil untuk saya (artinya masih menampilkan gambar rusak jika jalur file tidak benar)
Helmut

Pendekatan ini tidak berfungsi jika server melakukan pengalihan setiap kali gambar atau file tidak ada. Ini terjadi ketika situs menggunakan mod_rewrite atau semacam "aturan" lain bagaimana permintaan harus ditangani.
Erik Čerpnjak

28

Ini bukanlah jawaban atas pertanyaan awal Anda, tetapi cara yang lebih baik untuk melakukan apa yang Anda coba lakukan:

Daripada benar-benar mencoba mendapatkan favicon situs secara langsung (yang sangat merepotkan karena bisa jadi /favicon.png, /favicon.ico, /favicon.gif, atau bahkan /path/to/favicon.png), gunakan google:

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

Selesai.


4
Sintaksnya membuat sedikit kebingungan. Jadi di sini salah satu contohnya: <img src = " google.com/s2/favicons?domain=stackoverflow.com ">
Habeeb Perwad

19

Fungsi lengkap dari jawaban yang paling banyak dipilih:

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

Anda bisa menggunakannya seperti ini:

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

Oh! Saya telah pergi selama beberapa hari terakhir tetapi awal bulan hampir 24/7. Terima kasih telah memberitahu saya!
Pedro Lobito

Ini tidak berfungsi jika server tidak menanggapi kode HTTP apa pun (atau cUrl tidak menangkapnya). Yang cukup sering terjadi pada saya. Misalnya. dalam kasus gambar.
Vaci

bagaimana jika url dialihkan ke URL lain atau versi https? Dalam hal ini kode curl tidak akan dapat melakukan pekerjaan itu. cara terbaik adalah mendapatkan informasi header dan mencari string case-insensitive "200 ok".
Infoconic

@Informasi Anda dapat menambahkan curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);. Saya telah memperbarui jawaban untuk menangani 302pengalihan.
Pedro Lobito

18

Jika Anda berurusan dengan gambar, gunakan getimagesize. Tidak seperti file_exists, fungsi bawaan ini mendukung file jarak jauh. Ini akan mengembalikan array yang berisi informasi gambar (lebar, tinggi, tipe..dll). Yang harus Anda lakukan adalah memeriksa elemen pertama dalam array (lebarnya). gunakan print_r untuk menampilkan konten larik

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

Menghasilkan peringatan 404 ketika sumber daya jarak jauh tidak tersedia. Untuk saat ini, saya menanganinya dengan menekan penggunaan kesalahan @di depan getimagesize, tetapi merasa bersalah atas peretasan ini.

Dalam kasus saya ini adalah pendekatan terbaik, karena saya dialihkan setiap kali gambar / file tidak ada. Saya setuju bahwa kesalahan penekanan dengan @ tidak boleh dilakukan tetapi dalam hal ini itu diperlukan.
Erik Čerpnjak

Saya menemukan bahwa kami juga dapat menggunakan exif_imagetype, dan ini jauh lebih cepat stackoverflow.com/a/38295345/1250044
yckart

7

Ini dapat dilakukan dengan mendapatkan kode Status HTTP (404 = tidak ditemukan) yang dimungkinkan dengan file_get_contentsDokumen yang menggunakan opsi konteks. Kode berikut memperhitungkan pengalihan dan akan mengembalikan kode status tujuan akhir ( 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";

Jika Anda tidak ingin mengikuti pengalihan, Anda dapat melakukannya serupa ( 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";

Beberapa fungsi, opsi, dan variabel yang digunakan dijelaskan lebih detail di postingan blog yang saya tulis: HEAD first with PHP Streams .




Untuk informasi lebih lanjut tentang PHP, $http_response_headerlihat php.net/manual/en/reserved.variables.httpresponseheader.php .
Big McLargeHuge

1
Varian kedua bekerja untuk saya dan dibandingkan dengan panggilan file_get_contents default (tidak ada stream_context kustom) itu 50% lebih cepat, yaitu dari 3,4 detik menjadi 1,7 detik untuk permintaan.
Erik Čerpnjak

@ ErikČerpnjak: Jika tidak ada stream_context "ubahsuaian", ini adalah yang default. Anda bisa mendapatkan opsi dari konteks default dan melihat bagaimana mereka bervariasi dari konteks kustom Anda. Ini akan memberi Anda beberapa wawasan mengapa pengaturan waktu berbeda. - php.net/stream-context-get-default dan php.net/stream-context-get-options
hakre

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

Harus bekerja;)


add @ before function
Tebe

6

Fungsi bawaan PHP mungkin tidak berfungsi untuk memeriksa URL jika pengaturan allow_url_fopen dinonaktifkan untuk alasan keamanan. Curl adalah opsi yang lebih baik karena kami tidak perlu mengubah kode kami di tahap selanjutnya. Di bawah ini adalah kode yang saya gunakan untuk memverifikasi URL yang valid:

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

Mohon perhatikan opsi CURLOPT_SSL_VERIFYPEER yang juga memverifikasi URL yang dimulai dengan HTTPS.


6

Untuk mengecek keberadaan gambar, exif_imagetypesebaiknya lebih diutamakangetimagesize , karena jauh lebih cepat.

Untuk menekannya E_NOTICE, cukup tambahkan operator kontrol kesalahan ( @).

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

Sebagai bonus, dengan nilai yang dikembalikan ( IMAGETYPE_XXX) dari exif_imagetypekita juga bisa mendapatkan tipe mime atau ekstensi file dengan image_type_to_mime_type/ image_type_to_extension.


4

Solusi radikal akan menampilkan favicon sebagai gambar latar belakang dalam div di atas ikon default Anda. Dengan begitu, semua overhead akan ditempatkan pada klien sementara masih tidak menampilkan gambar yang rusak (gambar latar yang hilang diabaikan di semua browser AFAIK).


1
+1 jika Anda tidak memeriksa beberapa lokasi untuk favicon mereka (favicon.ico, favicon.gif, favicon.png) tampaknya ini adalah solusi terbaik
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

Anda bisa menggunakan yang berikut ini:

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

Bekerja untuk saya ketika mencoba memeriksa apakah ada gambar di URL


2

Kamu dapat memakai :

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

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

2

Ini berfungsi bagi saya untuk memeriksa apakah file jarak jauh ada di 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

Ada alternatif yang lebih canggih. Anda dapat melakukan pengecekan semua sisi klien menggunakan trik 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); };
});

Dari http://snipplr.com/view/18782/add-a-favicon-near-external-links-with-jquery/ (blog asli saat ini sedang tidak aktif)


1

semua jawaban di sini yang menggunakan get_headers () melakukan permintaan GET. Jauh lebih cepat / lebih murah untuk hanya melakukan permintaan HEAD.

Untuk memastikan bahwa get_headers () melakukan permintaan HEAD daripada GET, Anda harus menambahkan ini:

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

jadi untuk memeriksa apakah ada file, kode Anda akan terlihat seperti ini:

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 akan mengembalikan salah atau benar, jelas.


0

Tidak tahu apakah yang ini lebih cepat ketika file tidak ada dari jarak jauh, is_file () , tetapi Anda bisa mencobanya.

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

Dari dokumen: "Mulai dari PHP 5.0.0, fungsi ini juga dapat digunakan dengan beberapa pembungkus URL. Lihat Protokol dan Pembungkus yang Didukung untuk menentukan pembungkus mana yang mendukung kelompok fungsionalitas stat ()."
PatrikAkerstrand

Apakah maksud Anda ini dapat berfungsi jika Anda mendaftarkan pembungkus streaming? Edit pertanyaan Anda untuk menunjukkan contoh yang berfungsi dan saya akan menghapus suara negatif saya (dan memberi suara positif jika saya bisa). Tetapi untuk saat ini, saya menguji is_file dari php cli dengan file jarak jauh, dan ternyata salah.
greg0ire

tidak ada contoh yang berfungsi:var_dump(is_file('http://cdn.sstatic.net/stackoverflow/img/sprites.png')); bool(false)
greg0ire

0

Jika file tidak dihosting secara eksternal, Anda dapat menerjemahkan URL jarak jauh ke Path absolut di server web Anda. Dengan begitu Anda tidak perlu memanggil CURL atau file_get_contents, dll.

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

Catatan: Server web Anda harus mengisi DOCUMENT_ROOT untuk menggunakan fungsi ini


0

Jika Anda menggunakan framework Symfony, ada juga cara yang jauh lebih sederhana menggunakan 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;
}

Dokumen untuk HttpClient juga sangat bagus dan mungkin layak untuk dilihat jika Anda membutuhkan pendekatan yang lebih spesifik: https://symfony.com/doc/current/http_client.html


-1

Anda dapat menggunakan filesystem: gunakan Symfony \ Component \ Filesystem \ Filesystem; gunakan Symfony \ Component \ Filesystem \ Exception \ IOExceptionInterface;

dan periksa $ fileSystem = new Filesystem (); jika ($ fileSystem-> ada ('path_to_file') == true) {...

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.