我正在尝试找到图像的mime类型。 PHP有函数getimagesize
,但只有文件名,而我有一个图像“资源” - 即从imagecreatefromstring
创建的图像。
我发现函数imagesx
和imagesy
从资源返回宽度/高度,但我找不到任何告诉我来自资源的mime类型的函数。有人知道这样做的方法吗?
注意:由于设置了奇怪的服务器,我们无法从服务器读取/写入文件,只能通过FTP层(我从中读取图像数据)。
答案 0 :(得分:12)
如果您可以访问图像的二进制数据(使用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];
}
滥用流包装器会变得有点复杂。 至少如果我们不想摆弄全局变量。
// getimagesize() from string
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;
// note: @ suppresses "Read error!" notices if $imgdata isn't valid
return @getimagesize(self::$proto . '://');
}
static function getMimeType($imgdata) {
return is_array($gis = self::getImageSize($imgdata))
? $gis['mime']
: $gis;
}
// streamwrapper helper:
const unregister = null;
// register|unregister wrapper for the given protocol|scheme
// return registered protocol or null
static function register(
$proto = self::proto_default // protocol or scheme
) {
if (self::unregister === $proto) { // unregister if possible
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;
}
// streamwrapper API:
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;
}
/* uncomment this if needed
if ($this->fpos + $num_bytes > 65540 * 4) {
// prevent getimagesize() from scanning the whole file
// 65_540 is the maximum possible bytesize of a JPEG segment
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;
}
}
// usage:
//$imgdata = file_get_contents('path/lenna.jpg');
// if the default protocol is already registered
//GisFromString::register('other');
var_dump(GisFromString::getImageSize($imgdata));
echo GisFromString::getMimeType($imgdata);
答案 1 :(得分:10)
使用imagecreatefromstring
创建的图像不再具有MIME类型,它从原始格式解码并以GD的内部格式存储。
同样的问题是asked a while back,结果相同。
唯一的方法是在图像获得imagecreatefromstring
之前捕获图像,并以某种方式从中捕获大小信息。
你说你不能在你的系统上进行文件读/写操作,所以只是写出文件是不可能的。
getimagesize()无法读取变量这一事实已为人所知并感叹:http://bugs.php.net/bug.php?id=44239
那里的那个人提到了一个漂亮的解决方法:Registering a new stream wrapper that allows file operations on variables。
这是您服务器设置的一个选项吗?
答案 2 :(得分:8)
我知道这已经很老了,但万一有人像我一样碰到这个帖子......
从PHP 5.4.0发布的更好的选择: getimagesizefromstring
这个新功能与getimagesize完全相同,但允许您从流中检索信息。
答案 3 :(得分:0)
您可以使用PHP fileinfo函数。
$image_buffer = SomeFunctionToGetStringBufferFromGD();
$fileinfo = finfo_open();
$type = finfo_buffer($fileinfo, $image_buffer);
它使用magic numbers(与unix文件命令相同)来标识文件类型。