如果您可以访问图像的二进制数据(使用imagecreatefromstring()函数暗示了这一点),则可以手动检测文件类型:
function image_file_type_from_binary($binary) {
if (
!preg_match(
'/\A(?:(\xff\xd8\xff)|(GIF8[79]a)|(\x89PNG\x0d\x0a)|(BM)|(\x49\x49(?:\x2a\x00|\x00\x4a))|(FORM.{4}ILBM))/',
$binary, $hits
)
) {
return 'application/octet-stream';
}
static $type = array (
1 => 'image/jpeg',
2 => 'image/gif',
3 => 'image/png',
4 => 'image/x-windows-bmp',
5 => 'image/tiff',
6 => 'image/x-ilbm',
);
return $type[count($hits) - 1];
}
滥用流包装器会变得更加复杂。至少,如果我们不想摆弄全局变量的话。
class GisFromString {
const proto_default = 'gisfromstring';
protected static $proto = null;
protected static $imgdata = null;
static function getImageSize($imgdata) {
if (null === self::$proto) {
self::register();
}
self::$imgdata = $imgdata;
return @getimagesize(self::$proto . '://');
}
static function getMimeType($imgdata) {
return is_array($gis = self::getImageSize($imgdata))
? $gis['mime']
: $gis;
}
const unregister = null;
static function register(
$proto = self::proto_default // protocol or scheme
) {
if (self::unregister === $proto) {
if (null === self::$proto) {
return null;
}
if (!stream_wrapper_unregister(self::$proto)) {
return null;
}
$return = self::$proto;
self::$proto = null;
return $return;
}
if (!preg_match('/\A([a-zA-Z][a-zA-Z0-9.+\-]*)(:([\/\x5c]{0,3}))?/', $proto, $h)) {
throw new Exception(
sprintf('could not register invalid scheme or protocol name "%s" as streamwrapper', $proto)
);
}
if (!stream_wrapper_register($proto = $h[1], __CLASS__)) {
throw new Exception(
sprintf('protocol "%s" already registered as streamwrapper', $proto)
);
}
return self::$proto = $proto;
}
function stream_open($path, $mode) {
$this->str = (string) self::$imgdata;
$this->fsize = strlen($this->str);
$this->fpos = 0;
return true;
}
function stream_close() {
self::$imgdata = null;
}
function stream_read($num_bytes) {
if (!is_numeric($num_bytes) || $num_bytes < 1) {
return false;
}
if ($this->fpos + $num_bytes > $this->fsize) {
$num_bytes = $this->fsize - $this->fpos;
}
$read = substr($this->str, $this->fpos, $num_bytes);
$this->fpos += strlen($read);
return $read;
}
function stream_eof() {
return $this->fpos >= $this->fsize;
}
function stream_tell() {
return $this->fpos;
}
function stream_seek($off, $whence = SEEK_SET) {
if (SEEK_CUR === $whence) {
$off = $this->fpos + $off;
}
elseif (SEEK_END === $whence) {
$off = $this->fsize + $off;
}
if ($off < 0 || $off > $this->fsize) {
return false;
}
$this->fpos = $off;
return true;
}
}
var_dump(GisFromString::getImageSize($imgdata));
echo GisFromString::getMimeType($imgdata);