0

我正在使用 MySQL 数据库来保存一些字体。我需要使用自定义字体系列文本创建图像。我正在使用 SplTempFileObject 处理 setFont 方法,但这是 imagick 所说的:

Fatal error: Uncaught exception 'ImagickDrawException' with message 'The given font is not found in the ImageMagick configuration and the file ($_SERVER['DOCUMENT_ROOT]php:/temp) is not accessible' 

(当然 $_SERVER['DOCUMENT_ROOT'] 是真正的价值,我只是替换它):)

任何解决方案或者我必须在文件系统中保存字体?

这是代码:

 $image = new \Imagick();
 $draw = new \ImagickDraw();

 $temp = new \SplTempFileObject();
 $temp->fwrite($font->getFile()->getContent());

 $image->newImage(550, 50, "black");
 $draw->setFont($temp);

$font 是来自数据库的数据。我认为问题是因为 ImagickDraw::setFont() 相对于 DOC ROOT 搜索字体。

4

3 回答 3

7

该问题是由使用内存缓存的 SplTempFileObject 引起的,默认情况下最多缓存 2MB。 \SplTempFileObject->getFileName()will returnphp://temp \SplTempFileObject->getFileInfo()将返回一个空对象/文件指针 \SplTempFileObject->getRealPath()将始终返回一个空字符串!

如果您希望 PHP 在文件系统中写入一个真实文件,则必须提供内存限制0作为构造参数,但您仍然不会得到有效的SplFileInfo路径名或文件名,除了php://temp/maxmemory:0

是的:这很奇怪,与创建临时文件的“简单界面”相去甚远。

详情请查看http://php.net/manual/spltempfileobject.construct.php

返回,使用旧的tempfile()tempnam(). 我的解决方案:

代替 $file = new \SplTempFileObject();

我用 $file = new \SplFileObject(tempnam(sys_get_temp_dir(), rand()), 'w+');

于 2013-05-10T11:01:43.520 回答
0

我认为您的问题来自您的寻址错误。当您说"/".$temp->getFileName()您没有根据文档获得路径时。因此,由于您没有路径,因此您的前导“/”表示“从服务器根目录”。不酷。

您可以使用getRealPath做您想做的事。

于 2012-09-23T19:20:14.463 回答
0

Like others have said, there's a bug with \SplTempFileObject where even if you do pass 0 into the constructor, you still have a file that's in memory and therefore doesn't have a filepath/realpath.

I've built a tiny, simple PHP7+ class for this:

interface TemporaryFile {
    public function handle(\Closure $closure) : void;
    public function write(string $contents): void;
    public function getContents() : string;
    public function chmod(int $mode): void;
    public function getUri() : string; // aka realpath
    public function close() : void;
}

class IO
{
    /**
     * @return TemporaryFile
     */
    public static function getTemporaryFile() : TemporaryFile {
        return new class implements TemporaryFile {
            private $handle;

            public function __construct()
            {
                $this->handle = tmpfile();
            }

            public function handle(\Closure $closure) : void {
                $closure($this->handle);
            }

            public function getContents() : string {
                // according to PHP docs file_get_contents has much better performance
                // http://php.net/manual/en/function.fread.php
                return file_get_contents($this->getUri());
            }

            public function getUri() : string {
                return stream_get_meta_data($this->handle)['uri'];
            }

            public function close() : void {
                if (is_resource($this->handle))
                    fclose($this->handle);
            }

            public function write(string $contents): void
            {
                fwrite($this->handle, $contents);
            }

            public function chmod(int $mode): void
            {
                chmod($this->getUri(), $mode);
            }

            public function __destruct() {
                $this->close();
            }
        };
    }
}

To use it, just do this:

$file = IO::getTemporaryFile();
$file->write('foo');
var_dump($file->getContents()); // string(3) "foo"

You can see the aforementioned example in a working state here: https://3v4l.org/LYfan#output

And then you have a temporary file that's gonna self the destruct after the process is finished or the class is dereferenced.

于 2018-05-12T05:43:29.713 回答