DomPDF:图像不可读或为空。

37

2
PHP设置allow_url_fopen是否设置为true?如果您使用的是0.6.x版本,您可以加载dompdf/www/setup.php以查看安装中是否有任何红色标记。 - BrianS
12个回答

54

以下方法对我非常有效,至少在本地使用时是这样的,即便如此,

define("DOMPDF_ENABLE_REMOTE", false);

解决方法是将图片的SRC更改为服务器上的绝对路径,如下所示:

<img src="/var/www/domain/images/myimage.jpg" />

以下所有方法对我都奏效:

<img src="<?php echo $_SERVER["DOCUMENT_ROOT"].'/placeholder.jpg';?>"/>
<img src="<?php echo $_SERVER["DOCUMENT_ROOT"].'\placeholder.jpg';?>"/>
<img src="<?php echo $_SERVER["DOCUMENT_ROOT"].'./placeholder.jpg';?>"/>

$_SERVER["DOCUMENT_ROOT"] 是 C:/wamp/www/ZendSkeletonApplication/public

感谢这篇文章:lost in code


1
将图像转换为base64对我很有效 ->fit(80, 80) ->encode('data-url');``` - Olotin Temitope
使用绝对路径而不是相对路径能够解决我的问题。 - Nilesh Pansuriya

28

由于有另一个答案建议在module.config.php中启用远程选项,而我目前无法添加评论,我认为最好回答一下,在新版本的DomPDF中不存在此文件。

如果您需要在较新的版本中包含远程存储的图像,则必须将其作为选项传递给构造函数:

$dompdf = new Dompdf(array('enable_remote' => true));

这解决了我的问题。


在 Laravel 上对我有用,谢谢。 - ynsmtkl
这对我在远程图像方面非常有效。谢谢你的分享! - vanarie
enable_remote has synonyms, mentioned in https://github.com/dompdf/dompdf/blob/master/src/Options.php: elseif($key === 'isRemoteEnabled' || $key === 'is_remote_enabled' || $key === 'enable_remote') {$this->setIsRemoteEnabled($value);} - Arya
这个方法效果很好。 $dompdf = new Dompdf(); $dompdf->set_option("enable_remote", true); - Gjermund Dahl

15

好的,我也遇到了使用图片时同样的问题:

<img id="logo" src="/images/flags/fr.png" width="50" alt="Logo">

但是如果我在/images前面添加一个".",而不改变dompdf_config.custom.inc中的任何内容,则它可以工作。

<img id="logo" src="./images/flags/fr.png" width="50" alt="Logo">

希望这有所帮助


4
能工作的原因是因为最初您是在根目录中查找图像目录。 "./" 的意思只是“在这个目录中查找”。实际上,您可以删除“./”,它仍然可以工作。 - user3562712
2
你太棒了。我本来要重新排列很多东西的!! - Chad Caldwell
经过所有的尝试后,我找到了解决方案! - Marc

12

您可以使用base64编码的图像

<img src="{{'data:image/png;base64,' . base64_encode(file_get_contents(@$image))}}" alt="image" >

2
谢谢,伙计。我正在尝试从S3获取图像以在PDF中显示。对我来说非常顺利。 - Omer

11

现在(2018年5月)正确的方式是:

$options = new Options();
$options->set('isRemoteEnabled',true);      
$dompdf = new Dompdf( $options );

8

如果您的所有图像等资源都位于执行脚本的同一服务器上,则您实际上不需要打开isRemoteEnabled

为什么它无法加载您的图像

DomPdf通过其保护您免受攻击。 根据文档,以下内容将无法正常工作:

$dompdf = new Dompdf();
$dompdf->getOptions()->getChroot(); // something like 'C:\\laragon\\www\\your-local-website\\vendor\\dompdf\\dompdf'

$html = <<<HTML
<!DOCTYPE html>
<html lang="en">
    <body>
        <img src="C:\\laragon\\www\\your-local-website\\public\\img\\logo.png">
    </body>
</html>
HTML;

$dompdf->loadHtml($html);

你应该使用以下方法将 CHROOT 更改为你所需的绝对路径:

$dompdf->getOptions()->setChroot("C:\\laragon\\www\\your-local-website\\public");

然后,您可以在 HTML 中插入任何来自(可以嵌套)/public 文件夹的<img> 并设定相应的 src

安全提示

看起来只需将 Chroot 设置为应用程序根文件夹即可轻松完成,但不要这样做。这会打开一个恶意者可以利用的漏洞。据说,/public 中没有关键脚本,只有图像、公共文档、路由等。

使用提示

请注意,我使用了与文档中使用的不同的目录分隔符。我认为最好的做法是:

define('DS', DIRECTORY_SEPARATOR);

$public = ABSPATH . DS . 'public'; // ABSPATH is defined to be __DIR__ in root folder of your app
$image = $public . DS . 'logo' . DS . 'logo-md.png';

/* Optional */
$saveLocation = ABSPATH . DS . '..' . DS . 'private' . DS . 'invoices'; // Note that save location doesn't have to be in '/public' (or even in 'www')

$html = <<<HTML
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta http-equiv="content-type" content="text/html; charset=UTF-8">
        <style type="text/css">
            * {
                font-family: DejaVu Sans !important;
            }
            @page {
                margin: 0;
                padding: 0;
            }
            html, body {
                margin: 0;
                min-height: 100%;
                padding: 0;
            }          
        </style>
    </head>
    <body>
        <img src="{$image}">
    </body>
</html>
HTML;

$dompdf = new Dompdf();
$dompdf->getOptions()->setChroot($public);
$domPdf->loadHtml($html, 'UTF-8');
$domPdf->setPaper('A4', 'portrait');
$domPdf->render();

/* either */
$domPdf->stream($filename); // filename is optional

/* or */
$outputString = $domPdf->output();
$pdfFile = fopen($saveLocation, 'w');
fwrite($pdfFile, $outputString);
fclose($pdfFile);

3
我通过使用外部CSS的完整路径来解决这个问题。以下代码在我的Linux Ubuntu服务器上有效:
``` ```
``` ```
并且适用于图片。

在提供示例代码时,请将其作为解决问题的示例提供给提问者。 (例如,使用完整路径指向图像而不是样式表,因为此问题涉及图像。) - Loren

2

这里提供的解决方案都不适用于我。相反,我只是将图片进行了base64编码,然后它就起作用了。你可以使用这个工具


1
相同于。没有任何解决方案可行。在最后尝试了 base64,感谢这条评论,它起作用了。 - Keval Shah

1

我在加载本地图片时遇到了这个问题,后来找到了解决方法

$dompdf->getOptions()->setChroot($path_to_images);

这还不够,我还需要设置

chdir($path_to_images);

1

为了满足我们的需求,我们必须将页面上的所有图像转换为base64格式,因为pdf应该可以离线使用。我们的代码位于控制器类中,但您可以根据需要进行修改。

以下是代码:


    /**
     * Convert images to Base64 so it's included in the PDF.
     *
     * @param $html  Full html render of the page.
     */
    public function convertReportImagesToURI($html): string
    {
        $doc = new DOMDocument();
        libxml_use_internal_errors(true);
        $doc->loadHTML($html);
        $tags = $doc->getElementsByTagName('img');
        $imgArr = array();

        // Iterate over all image tags.
        foreach ($tags as $tag) {
            // Get the src attribute.
            $imgSrc = $tag->getAttribute('src');

            // Convert to base64.
            $base64src = self::getImageDataURI($imgSrc);
            $tag->setAttribute('src', $base64src);
        }
        return $doc->saveHTML();
    }

    /**
     * This does the actual encoding.
     */
    public static function getImageDataURI($image, $mime = ''): string
    {
        // Director::absoluteURL('/') gets the base url of the site.
        // We had to remove the leading slash of the image hence the use of substr.
        // If your images have absolute urls you will need to modify this.
        $imageLocation = Director::absoluteURL('/') . substr($image, 1);
        // Get the image location. remove leading slash on image url.
        return 'data:' . self::get_image_mime_type($imageLocation) . ';base64,' . base64_encode(file_get_contents($imageLocation));
    }

    /**
     * https://dev59.com/oF8e5IYBdhLWcg3wRIpQ#45054843
     * @param $image_path
     * @return string
     */
    public static function get_image_mime_type($image_path): string
    {
        $mimes  = array(
            IMAGETYPE_GIF => "image/gif",
            IMAGETYPE_JPEG => "image/jpg",
            IMAGETYPE_PNG => "image/png",
            IMAGETYPE_SWF => "image/swf",
            IMAGETYPE_PSD => "image/psd",
            IMAGETYPE_BMP => "image/bmp",
            IMAGETYPE_TIFF_II => "image/tiff",
            IMAGETYPE_TIFF_MM => "image/tiff",
            IMAGETYPE_JPC => "image/jpc",
            IMAGETYPE_JP2 => "image/jp2",
            IMAGETYPE_JPX => "image/jpx",
            IMAGETYPE_JB2 => "image/jb2",
            IMAGETYPE_SWC => "image/swc",
            IMAGETYPE_IFF => "image/iff",
            IMAGETYPE_WBMP => "image/wbmp",
            IMAGETYPE_XBM => "image/xbm",
            IMAGETYPE_ICO => "image/ico");

        if (($image_type = exif_imagetype($image_path))
            && (array_key_exists($image_type, $mimes))) {
            return $mimes[$image_type];
        } else {
            return '';
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接