【问题标题】:Broken Images within phpwkhtmltopdfphpwkhtmltopdf中的破碎图像
【发布时间】:2018-10-07 22:42:25
【问题描述】:

需要注意的是,我已经在两个不同的服务器上进行了测试,Debian 9 和 Ubuntu 14.04,同样的错误仍然存​​在。现在我正在使用带有 PHP 5 的 Ubuntu 14.04,我已经安装了 composer,我已经正确安装了 wkhtmltopdf 和 phpwkhtmltopdf。我怎么知道这个? wkhtmltopdf/image 可以通过 CLI 工作,phpwkhtmltopdf 也可以通过 PHP 工作,但是当我尝试将图像作为内联显示发送到客户端或下载图像时会损坏。例如;

  1. 访问所需的 url,为我们提供 test.php
  2. Phpwkhtmltopdf 将发送与 CLI 版本 wkhtmltopdf 挂钩的命令
  3. 加载页面后,它将访问 google.com,将屏幕截图保存在磁盘上 /var/www/html/tmp/page.jpg 并且该图像可以正常打开/显示,但是当我尝试使用 $image->send('page.jpg'); 时,发送的图像已损坏/无法打开。

我对系统做了两处更改,我在 apache2 中禁用了 mod_deflate,并且我还在 apache2 的 php.ini 配置文件中增加了 max_filesize 选项。

依赖关系

现场示例

http://155.254.35.63/test.php // Generate the image
http://155.254.35.63/tmp/page.png // The image file generated

test.php

<?php

ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

?>

<?php

$loader = require __DIR__ . '/vendor/autoload.php';

?>

<?php

use mikehaertl\wkhtmlto\Image;

$image = new \mikehaertl\wkhtmlto\Image('https://www.google.co.uk/search?q=what+is+the+time&oq=what+is+the+time&aqs=chrome.0.69i59j69i60l3j0l2.2977j0j4&sourceid=chrome&ie=UTF-8');
$image->setOptions(array(
'binary' => '/usr/local/bin/wkhtmltoimage',
'type' => 'png'
));

$image->saveAs('/var/www/html/tmp/page.png');

header('Content-Type: image/png');
echo file_get_contents('/var/www/html/tmp/page.jpg');

?>

File.php(第 72 到 83 行)

<?php
namespace mikehaertl\tmp;

/**
 * File
 *
 * A convenience class for temporary files.
 *
 * @author Michael Härtl <haertl.mike@gmail.com>
 * @version 1.1.0
 * @license http://www.opensource.org/licenses/MIT
 */
class File
{
    /**
     * @var bool whether to delete the tmp file when it's no longer referenced or when the request ends.
     * Default is `true`.
     */
    public $delete = true;

    /**
     * @var string the name of this file
     */
    protected $_fileName;

    /**
     * Constructor
     *
     * @param string $content the tmp file content
     * @param string|null $suffix the optional suffix for the tmp file
     * @param string|null $prefix the optional prefix for the tmp file. If null 'php_tmpfile_' is used.
     * @param string|null $directory directory where the file should be created. Autodetected if not provided.
     */
    public function __construct($content, $suffix = null, $prefix = null, $directory = null)
    {
        if ($directory===null) {
            $directory = self::getTempDir();
        }

        if ($prefix===null) {
            $prefix = 'php_tmpfile_';
        }

        $this->_fileName = tempnam($directory,$prefix);
        if ($suffix!==null) {
            $newName = $this->_fileName.$suffix;
            rename($this->_fileName, $newName);
            $this->_fileName = $newName;
        }
        file_put_contents($this->_fileName, $content);
    }

    /**
     * Delete tmp file on shutdown if `$delete` is `true`
     */
    public function __destruct()
    {
        if ($this->delete) {
            unlink($this->_fileName);
        }
    }

    /**
     * Send tmp file to client, either inline or as download
     *
     * @param string|null $filename the filename to send. If empty, the file is streamed inline.
     * @param string $contentType the Content-Type header
     * @param bool $inline whether to force inline display of the file, even if filename is present.
     */
    public function send($filename = null, $contentType, $inline = false)
    {
        header('Pragma: public');
        header('Expires: 0');
        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
        header('Content-Type: image/png');
        header('Content-Transfer-Encoding: binary');

        if ($filename!==null || $inline) {
            $disposition = $inline ? 'inline' : 'attachment';
            header("Content-Disposition: $disposition; filename=\"$filename\"");
        }

        readfile($this->_fileName);
    }

    /**
     * @param string $name the name to save the file as
     * @return bool whether the file could be saved
     */
    public function saveAs($name)
    {
        return copy($this->_fileName, $name);
    }

    /**
     * @return string the full file name
     */
    public function getFileName()
    {
        return $this->_fileName;
    }

    /**
     * @return string the path to the temp directory
     */
    public static function getTempDir()
    {
        if (function_exists('sys_get_temp_dir')) {
            return sys_get_temp_dir();
        } elseif ( ($tmp = getenv('TMP')) || ($tmp = getenv('TEMP')) || ($tmp = getenv('TMPDIR')) ) {
            return realpath($tmp);
        } else {
            return '/tmp';
        }
    }

    /**
     * @return string the full file name
     */
    public function __toString()
    {
        return $this->_fileName;
    }
}

php.ini

;;;;;;;;;;;;;;;;
; File Uploads ;
;;;;;;;;;;;;;;;;

; Whether to allow HTTP file uploads.
; http://php.net/file-uploads
file_uploads = On

; Temporary directory for HTTP uploaded files (will use system default if not
; specified).
; http://php.net/upload-tmp-dir
;upload_tmp_dir = /var/www/html/tmp

; Maximum allowed size for uploaded files.
; http://php.net/upload-max-filesize
upload_max_filesize = 50M

; Maximum number of files that can be uploaded via a single request
max_file_uploads = 20

apache 日志文件中有 none (0) 错误,这真的让我无法理解问题所在。我试图通过开发人员找到解决方案,但没有看;

https://github.com/mikehaertl/phpwkhtmltopdf/issues/278

感谢您对此的帮助。

【问题讨论】:

    标签: php apache image-processing wkhtmltoimage


    【解决方案1】:

    我已经检查了您的测试站点生成的 page.jpg 文件。文件本身是完整的。这意味着您的管道没有问题。

    文件标题显示,您的文件不是标准的 JPEG 文件,而是 JFIF 变体。看看您是否可以将库设置为生成 PNG 文件来解决此问题。

    编辑:现在我看到生成的文件是正确的,看看你是否可以只流式传输内容而不是使用 $image->send。自己发送:

    header('Content-Type: image/png');
    echo file_get_contents('/var/www/html/tmp/page.jpg');
    

    【讨论】:

    • 嗨,我犯了一个错误,我已经改变了,在 file.php 中这一行 (header('Content-Type: image/jpg');) 实际上不是 (image/png ) 不管我都试过了,但它没有任何作用。
    • 当图像文件的内容不被识别时不会有什么不同。您实际上可以将 jpg 文件命名为 png,然后仍将其加载到图像标签中。我用它来测试图像。您必须更改库调用本身。到目前为止,它仍在发出 JFIF 标头。
    • 我希望我知道你的意思,我将如何更改库调用?
    • 在 $image->setoptions 中,将类型设置为 'png'。不确定库是否支持它。试一试。
    • 我在将其更改为 jpg mate 之前尝试过,同样的问题。作为参考,我在 File.php 中将 content-type 更改为 png,并且在 test.php 中将所有出现的 jpg 更改为 png,您可以在此处查看它在访问 /test.php 时生成的图像 - 155.254.35.63/tmp/page.png,如您所见,非常好,这也让我相信它与 File.php 中的标题有关。
    猜你喜欢
    • 2017-10-28
    • 2023-03-25
    • 2021-08-10
    • 1970-01-01
    • 2017-08-24
    • 2015-06-13
    • 1970-01-01
    • 1970-01-01
    • 2015-09-02
    相关资源
    最近更新 更多