Я пытаюсь найти тип mime изображения. PHP имеет функцию getimagesize
но для этого требуется только имя файла, тогда как вместо этого у меня есть «ресурс» изображения, то есть изображение, созданное из imagecreatefromstring
.
Я нашел функции imagesx
и imagesy
которые возвращают ширину / высоту из ресурса, но я не могу найти какую-либо функцию, которая сообщит мне тип mime из ресурса. Кто-нибудь знает, как это сделать?
Примечание. Из-за странного настроенного сервера мы не можем нормально читать и записывать файлы с сервера только через уровень FTP (откуда я читаю данные изображения).
Я знаю, что это довольно старый, но на всякий случай кто-то сталкивается с этим сообщением, как я …
Лучший вариант, который он выпустил из PHP 5.4.0: getimagesizefromstring
Эта новая функция точно такая же, как и для getimagesize, но позволяет вам извлекать информацию из потока.
Если у вас есть доступ к двоичным данным изображения (как предполагает использование 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);
Изображение, созданное с использованием imagecreatefromstring
больше не имеет типа MIME, оно декодируется из собственного формата и сохраняется во внутреннем формате GD.
Тот же вопрос был задан некоторое время назад с тем же результатом.
Единственный способ пойти – это поймать изображение, прежде чем он получит imagecreatefromstring
ed, и как-то поймает информацию о размере.
Вы говорите, что вы не можете выполнять операции чтения / записи файлов в своей системе, поэтому просто написать файл невозможно.
Тот факт, что getimagesize () не может читать из переменных, известен и посетован: http://bugs.php.net/bug.php?id=44239
Парень там упоминает отличный способ: Регистрация новой обтекателя потока, которая позволяет файловые операции над переменными .
Это опция для настройки вашего сервера?
Вы можете использовать функции PHP fileinfo.
$image_buffer = SomeFunctionToGetStringBufferFromGD(); $fileinfo = finfo_open(); $type = finfo_buffer($fileinfo, $image_buffer);
Он использует магические числа (такие же, как команда файла unix) для идентификации типа файла.