13

我知道至少有 10 个相同的问题有答案,但似乎没有一个能完美地为我工作。我正在尝试检查是否存在内部或外部图像(图像 URL 是否有效?)。

  1. fopen($url, 'r')除非我使用失败@fopen()

    Warning: fopen(http://example.com/img.jpg) [function.fopen]: failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found in file.php on line 21
    
  2. getimagesize($img)图像不存在时失败(PHP 5.3.8):

    Warning: getimagesize() [function.getimagesize]: php_network_getaddresses: getaddrinfo failed
    
  3. CURL 失败是因为某些服务器不支持它(尽管它几乎无处不在)。
  4. fileExists()失败是因为它不适用于外部 URL,并且无法检查我们是否正在处理图像。

作为此类问题最常见答案的四种方法是错误的。这样做的正确方法是什么?

4

9 回答 9

15

getimagesize($img) fails when image doesn't exist:我不确定你明白你想要什么......

来自 PHP 文档

getimagesize() 函数将确定任何给定图像文件的大小,并返回尺寸以及文件类型和要在普通 HTML IMG 标记和相应 HTTP 内容类型中使用的高度/宽度文本字符串。

失败时,返回 FALSE。

例子

$img = array("http://i.stack.imgur.com/52Ha1.png","http://example.com/img.jpg");
foreach ( $img as $v ) {
    echo $v, getimagesize($v) ? " = OK  \n" : " = Not valid \n";
}

输出

http://i.stack.imgur.com/52Ha1.png = OK  
http://example.com/img.jpg = Not valid 

getimagesize工作得很好

编辑

@Paul 。但是您的问题本质上是在说“我该如何处理,这样在出现错误情况时我就不会收到错误”。答案是“你不能”。因为所有这些函数都会在出现错误条件时触发错误。所以(如果你不想要错误)你压制它。这些在生产中都不重要,因为无论如何你都不应该显示错误;-) – DaveRandom

于 2012-12-19T16:47:47.867 回答
14

此代码实际上是检查文件...但是,它确实适用于图像!

$url = "http://www.myfico.com/Images/sample_overlay.gif";
$header_response = get_headers($url, 1);
if ( strpos( $header_response[0], "404" ) !== false )
{
   // FILE DOES NOT EXIST
} 
else 
{
   // FILE EXISTS!!
}
于 2012-12-19T16:48:29.023 回答
4
function checkExternalFile($url)
{
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_NOBODY, true);
    curl_exec($ch);
    $retCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    return $retCode;
}

$fileExists = checkExternalFile("http://example.com/your/url/here.jpg");

// $fileExists > 400 = not found
// $fileExists = 200 = found.
于 2013-08-23T08:52:22.303 回答
1

如果您使用 PHP >=5.0.0,您可以向 fopen 传递一个附加参数来指定 HTTP 的上下文选项,其中包括是否忽略失败状态代码。

$contextOptions = array( 'http' => array('ignore_errors' => true));

$context = stream_context_create($contextOptions);

$handle = fopen($url, 'r', false, $context);
于 2012-12-19T16:45:11.727 回答
0

您可以为此使用 PEAR/HTTP_Request2 包。你可以在这里找到

这里有一个例子。该示例要求您已正确安装或下载 HTTP_Request2 包。它使用旧式插座适配器,而不是卷曲。

<?php

require_once 'HTTP/Request2.php';
require_once 'HTTP/Request2/Adapter/Socket.php';

$request = new HTTP_Request2 (
    $your_url, 
    HTTP_Request2::METHOD_GET,
    array('adapter' => new HTTP_Request2_Adapter_Socket())
);

switch($request->send()->getResponseCode()) {

    case 404 : 
        echo 'not found';
        break;

    case 200 :
        echo 'found';
        break;

    default :
        echo 'needs further attention';

}
于 2012-12-19T16:41:38.467 回答
0

使用fsockopen,连接到服务器,发送HEAD请求并查看您返回的状态。

唯一需要注意的问题是该域是否不存在。

示例代码:

$file = "http://example.com/img.jpg";
$path = parse_url($file);
$fp = @fsockopen($path['host'],$path['port']?:80);
if( !$fp) echo "Failed to connect... Either server is down or host doesn't exist.";
else {
  fputs($fp,"HEAD ".$file." HTTP/1.0\r\n"
     ."Host: ".$path['host']."\r\n\r\n");
  $firstline = fgets($fp);
  list(,$status,$statustext) = explode(" ",$firstline,3);
  if( $status == 200) echo "OK!";
  else "Status ".$status." ".$statustext."...";
}
于 2012-12-19T16:43:20.227 回答
0

我发现 try catch 是最好的解决方案。它对我很好。

try{
      list($width, $height) = getimagesize($h_image->image_url);
   }
catch (Exception $e)
    {
    }
于 2015-12-31T11:33:08.157 回答
0

我知道你写了“没有卷曲”,但仍然有人可能会觉得这很有帮助:

function curl_head($url) {

    $ch = curl_init($url);

    //curl_setopt($ch, CURLOPT_USERAGENT, 'Your user agent');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_HEADER, 1); # get headers
    curl_setopt($ch, CURLOPT_NOBODY, 1); # omit body
    //curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1); # do SSL check
    //curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); # verify domain within cert
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); # follow "Location" redirs
    //curl_setopt($ch, CURLOPT_TIMEOUT_MS, 700); # dies after 700ms

    $result = curl_exec($ch);

    curl_close($ch);

    return $result;
}

print_r(curl_head('https://www.example.com/image.jpg'));

您将看到类似这样的内容HTTP/1.1 200 OKHTTP/1.1 404 Not Found 在返回的标头数组中。您还可以使用curl multi.

于 2017-02-27T09:27:40.440 回答
-1

有多个步骤,没有单一的解决方案:

  1. 验证网址
  2. 检查文件是否可用(可以直接用第3步完成)
  3. 将图像下载到 tmp 文件中。
  4. 使用 getimagesize 检查图像的大小。

对于此类工作,您可以捕获异常并妥善处理它们以定义您的答案。在这种情况下,您甚至可以抑制错误,因为它们的欺骗可能会失败。因此,您可以正确处理错误。

因为在没有下载实际图像的情况下不可能对其进行 100% 检查。因此,第 1 步和第 2 步是必需的,第 3 步和第 4 步是可选的,以获得更明确的答案。

于 2012-12-19T16:43:29.593 回答