Reputation: 11
Things to note, I have tested this on two different servers, Debian 9 and Ubuntu 14.04 and the same error persists. Right now I am using Ubuntu 14.04 with PHP 5, I have installed composer, I have installed both wkhtmltopdf and phpwkhtmltopdf correctly. How do I know this? Well wkhtmltopdf/image works via CLI, phpwkhtmltopdf also works via PHP however when I attempt to send the image to the client as an inline display or download the image corrupts. For example;
/var/www/html/tmp/page.jpg
and that image opens/displays fine, however when I attempt to use $image->send('page.jpg');
the sent image is corrupt/wont open.I have made two changes to the system, I have disabled mod_deflate within apache2 and I have also increased the max_filesize options within apache2's php.ini config file.
Dependencies
Live Example
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 (Lines 72 to 83)
<?php
namespace mikehaertl\tmp;
/**
* File
*
* A convenience class for temporary files.
*
* @author Michael Härtl <[email protected]>
* @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
There are none (0) errors in the apache log file, which is really putting me off what the issue could be. I have attempted to find a resolution with the dev but no look;
https://github.com/mikehaertl/phpwkhtmltopdf/issues/278
Id appreciate the help on this one.
Upvotes: 1
Views: 1346
Reputation: 3903
I have examined the page.jpg file your test site generates. The file itself is intact. This means there is nothing wrong with your plumbing.
The file header shows that instead of a standard JPEG file, yours is a JFIF variant. See if you can set the library to generate a PNG file to workaround this issue.
Edit: now that I see the generated file is correct, see if you can just stream the content instead of using $image->send. Send it youself:
header('Content-Type: image/png');
echo file_get_contents('/var/www/html/tmp/page.jpg');
Upvotes: 1