如何检查使用PHP是否存在远程文件?
我能find的最好的, if
fclose
fopen
types的东西,使页面加载真的很慢。
基本上我想要做的是以下几点:我有一个网站列表,我想显示他们的favicons旁边。 但是,如果一个网站没有一个,我想用另一个图像replace而不是显示一个破碎的图像。
您可以指示curl通过CURLOPT_NOBODY使用HTTP HEAD方法。
或多或less
$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);
无论如何,你只节约了HTTP传输的开销,而不是TCP连接的build立和closures。 而作为小图标,你可能没有看到太多的改善。
如果结果太慢,在本地caching结果似乎是一个好主意。 HEAD检查文件的时间,并将其返回到标题中。 您可以像浏览器一样来获取图标的CURLINFO_FILETIME。 在caching中,您可以存储URL => [favicon,timestamp]。 然后,您可以比较时间戳并重新加载图标。
馅饼说你可以使用cURL。 你可以得到cURL只给你头,而不是身体,这可能会使它更快。 一个坏域可能总是需要一段时间,因为你会等待请求超时; 你可以用cURL改变超时时间。
这里是例子:
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'; }
CoolGoose的解决scheme是好的,但这对于大文件来说更快(因为它只尝试读取1个字节):
if (false === file_get_contents("http://example.com/path/to/image",0,null,0,1)) { $image = $default_image; }
这不是你原来的问题的答案,而是一个更好的方法来做你想做的事情:
而不是实际试图直接获取网站的图标(这是一个皇室的痛苦,因为它可能是/favicon.png,/favicon.ico,/ favicon.gif,甚至/path/to/favicon.png),使用谷歌:
<img src="http://www.google.com/s2/favicons?domain=[domain]">
完成。
如果您正在处理图像,请使用getimagesize。 与file_exists不同,这个内置函数支持远程文件。 它将返回一个包含图像信息(宽度,高度,types等)的数组。 你所要做的就是检查数组中的第一个元素(宽度)。 使用print_r输出数组的内容
$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"; }
if (false === file_get_contents("http://example.com/path/to/image")) { $image = $default_image; }
应该工作;)
这可以通过获取使用上下文选项的file_get_contents
Docs可能获得的HTTP状态代码(404 =未find)来完成。 以下代码将redirect考虑在内,并将返回最终目标( 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";
如果你不想遵循redirect,你可以做类似( 演示 ):
$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";
在我写的一篇博客文章中更详细地解释了一些正在使用的函数,选项和variables: HEAD首先使用PHP Streams 。
由于安全原因,如果allow_url_fopen设置为off,PHP的内置函数可能无法检查URL。 curl是一个更好的select,因为我们不需要在后期更改我们的代码。 以下是我用来validation有效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; }
请注意CURLOPT_SSL_VERIFYPEER选项,它也validationURL以HTTPS开头。
一个彻底的解决办法是将图标显示为默认图标上方的div中的背景图像。 这样,所有的开销将被放置在客户端上,同时仍然不显示破碎的图像(在所有浏览器AFAIK中忽略丢失的背景图像)。
答案最多的完整curlfunction:
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;} }
你可以像这样使用它:
if(remote_file_exists($url)) { //file exists, do something }
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!!!"; }
您可以使用 :
$url=getimagesize(“http://www.flickr.com/photos/27505599@N07/2564389539/”); if(!is_array($url)) { $default_image =”…/directoryFolder/junal.jpg”; }
您可以使用以下内容:
$file = 'http://mysite.co.zahttp://img.dovov.comfavicon.ico'; $file_exists = (@fopen($file, "r")) ? true : false;
在尝试检查URL上是否存在图像时为我工作
您应该发出HEAD请求,而不是GET请求,因为根本不需要URI内容。 正如馅饼所述,你应该检查状态码(在200-299范围内,你可以select跟随3xxredirect)。
答案的问题包含了很多可能有用的代码示例: PHP / Curl:HEAD请求在某些站点上需要很长时间
还有一个更复杂的select。 你可以使用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); }; });
从http://snipplr.com/view/18782/add-a-favicon-near-external-links-with-jquery/ (原来的博客是目前下来)
所有使用get_headers()的答案都在做GET请求。 做一个HEAD请求会更快/更便宜。
为了确保get_headers()做一个HEAD请求,而不是一个GET,你应该添加这个:
stream_context_set_default( array( 'http' => array( 'method' => 'HEAD' ) ) );
所以要检查一个文件是否存在,你的代码看起来像这样:
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显然会返回false或true。
为了检查图像的存在, exif_imagetype
应该优于getimagesize
,因为它更快。
要抑制E_NOTICE
,只需预先安装错误控制运算符( @
)。
if (@exif_imagetype($filename)) { // Image exist }
作为奖励,利用来自exif_imagetype
的返回值( IMAGETYPE_XXX
),我们也可以得到带有image_type_to_mime_type
/ image_type_to_extension
的mimetypes或文件扩展名。
当文件不存在时,不知道这个文件是否更快, is_file() ,但你可以试试 。
$favIcon = 'default FavIcon'; if(is_file($remotePath)) { $favIcon = file_get_contents($remotePath); }