54

This has been asked to some degree before but there are no solutions or accepted answers and I'd like to try and be more comprehensive in my question so:

I'm trying to WKHTMLTOPDF up and running via PHP on a shared server (in this case it's MediaTemple (gs)). According to the host there is no reason this won't work and in fact it is working via SSH. So...

I've tried a variety of things, the most basic does nothing, just silently fails:

exec("/path/to/binary/wkhtmltopdf http://www.google.com pdf1.pdf");

- Source: Question on Stack Overflow

The full PHP bindings along with the following give me errors, which despite my best Googling I can't figure out:

Call:

$html = file_get_contents("http://www.google.com");
$pdf = new WKPDF();
$pdf->set_html($html);
$pdf->render();
$pdf->output(WKPDF::$PDF_EMBEDDED,'sample.pdf');

- Source: WKHTMLTOPDF on Google Code

Error:

Fatal error: Uncaught exception 'Exception' with message 'WKPDF didn't return
any data. <pre>Loading pages (1/6) [> ] 0% [======> ] 10% terminate called
after throwing an instance of 'std::bad_alloc' what(): std::bad_alloc </pre>'
in /path/to/wkhtmltopdf.php:206 Stack trace: #0 /path/to/index.php(8):
WKPDF->render() #1 {main} thrown in /path/to/wkhtmltopdf.php on line 206

And once I got this (below is an extract as I can't reproduce it now):

Qt Concurrent has caught an exception thrown from a worker thread. This is not
supported, exceptions thrown in worker threads must be caught before
control returns to Qt Concurrent.

I've also tried a few other options but with the same results; no PDF. So what do I do now, how do I figure out what's wrong? My PHP level is on the basic side but I'll do my best.

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
Jamie
  • 786
  • 1
  • 7
  • 12
  • 1
    can you create a pdf directly, using the terminal? – Chris Ghenea Jul 24 '11 at 14:14
  • Actually I should have updated this but the project is on hold. I have got this working though not entirely satisfactorily. First I had to place **all** the HTML source files & dependancies in the same directory as the executable (no sub dirs at all, even for images). Second I put the CSS & JS into the HTML header. Finally I put a `memory_get_usage();` in the WKHTMLTOPDF function which apparently triggers garbage collection. The first two points reduced the number of errors the third stopped them all together, now it works perfectly even @font-face which was reported as broken. – Jamie Jul 25 '11 at 11:31
  • I know this is old, and may not be necessary for you anymore, but how did you install wkhtmltopdf on MediaTemple (gs) in the first place? Have you had any experience installing using the latest versions? – Ian Tearle Apr 29 '15 at 14:41
  • I was just running it as a static binary – upload wkhtmltopdf to the server and run it via the exec command above. I am still using wkhtmltopdf including the latest versions which are good but have moved away from Media Temple to a virtual server setup with wkhtmltopdf actually installed. I've found it much more reliable that way. – Jamie Apr 29 '15 at 15:14

7 Answers7

42

You can also try my project here. It provides a clean OO interface to the command line utility:

https://github.com/mikehaertl/phpwkhtmltopdf

Usage is very simple:

<?php
use mikehaertl\wkhtmlto\Pdf; 

$pdf = new Pdf;

// Add a HTML file, a HTML string or a page from a URL
$pdf->addPage('/home/joe/page.html');
$pdf->addPage('<html>....</html>');
$pdf->addPage('http://google.com');

// Add a cover (same sources as above are possible)
$pdf->addCover('mycover.html');

// Add a Table of contents
$pdf->addToc();

// Save the PDF
$pdf->saveAs('/tmp/new.pdf');

// ... or send to client for inline display
$pdf->send();
Michael Härtl
  • 8,428
  • 5
  • 35
  • 62
  • 9
    A "true" tutorial could be really nice like install on windows system, install without composer(some people don't use it), list all option available... – Core972 Sep 05 '14 at 09:09
  • 1
    use mikehaertl\wkhtmlto\Pdf; where can I get this files ... Please help me I new to PDF generation @Core972 – Anudeep GI Oct 03 '14 at 04:02
  • 1
    @Anudeep Please check out the URL above, you'll find documentation there. For further problems please open an issue over at github. – Michael Härtl Oct 03 '14 at 11:14
  • 4
    how do I install WITHOUT composer? I don't have access to the server! I tried including all three files and 'use mikehaertl\wkhtmlto\Pdf;', but it returns me an error: "Class 'mikehaertl\shellcommand\Command' not found". Can you help me? – Rafael Moni Dec 04 '14 at 11:47
  • 3
    @RafaelMoni You could copy it from a box that has `composer` installed: Install the package in some temp location, and then copy the `vendor/` directory into your project. – Michael Härtl Dec 05 '14 at 08:20
  • Nice, I'm gonna test as soon as I go back to that project – Rafael Moni Dec 05 '14 at 15:58
  • How do you add a page generated with Twig??? In this case, `Twig` comes from `$twig->render('path/to/file.twig',['some' => 'params'])` – Pathros Apr 07 '16 at 18:45
  • @MichaelHärtl I tried installing your package on github, it's not generating the autoload file when I used composer to install the package – unixmiah Apr 25 '16 at 17:12
  • Still a great library in 2023. Using in a classroom project and working nicely. – Woody Feb 04 '23 at 21:00
16

Have a look at snappy, a PHP5 library allowing thumbnail, snapshot or PDF generation from a url or a html page. It's a wrapper for wkhtmltopdf/wkhtmltoimage.

til
  • 161
  • 1
  • 2
10

For Linux:

exec('wkhtmltopdf http://somesite.com /home/user/file.pdf 2>&1');

For Windows:

<?php
exec('C://abc//wkhtmltopdf http://google.html form1.pdf');

echo "PDF Created Successfully";
?>
soft genic
  • 2,016
  • 3
  • 27
  • 44
10

You may want to set up proper headers and set it to application/pdf as well as setting it to inline so that people can see it in their browsers (almost every recent browser supports this) and save it if they want. This is the code that I'm using:

exec("/usr/local/bin/wkhtmltopdf ../uploads/test.pdf");
$file = "../uploads/test.pdf";
$pdf = file_get_contents("../uploads/test.pdf");

header('Content-Type: application/pdf');
header('Cache-Control: public, must-revalidate, max-age=0'); // HTTP/1.1
header('Pragma: public');
header('Expires: Sat, 26 Jul 1997 05:00:00 GMT'); // Date in the past
header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
header('Content-Length: '.strlen($pdf));
header('Content-Disposition: inline; filename="'.basename($file).'";');
ob_clean(); 
flush(); 
echo $pdf;
?>
Brian F
  • 119
  • 1
  • 6
5

To create a pdf from php (on linux) you must use a wrapper.

$cmd = '/usr/bin/xvfb-run --server-args="-screen 0, 1920x1080x24" /usr/bin/wkhtmltopdf http://google.com /tmp/google.pdf';

exec($cmd);
  • 1
    The reason for this is that `wkhtmltopdf` requires X server support for the fonts and images and `xvfb-run` can provide that support. – Mikko Rantalainen Jul 11 '14 at 12:05
  • 1
    This is great - and I think it's the only response that is actually answering the question. Lots of work-a-rounds and suggested alternative approaches, but yours addresses the real concern. – ChronoFish Jan 25 '18 at 14:54
  • works after I added apostrophes to url and path to destination file – Michal - wereda-net Feb 26 '19 at 14:19
2

This worked for me as a way to pre-generate a PDF report then use a unique session ID to fetch it from the requesting page (of the same session).

$cmd = "/usr/local/bin/wkhtmltopdf 'http://127.0.0.1/myApp/pdfReport.php?key=something' tmp_reports/report_".$_POST['sessionid'].".pdf";
exec($cmd);
Jason
  • 719
  • 9
  • 19
2

And what happens when you run :

$out = array();
exec("/path/to/binary/wkhtmltopdf http://www.google.com pdf1.pdf", $out);
print_r($out);

My guess is that since you are not specifying any folder for the file, it will try to write it to the current working directory. It could be (well most probably this is the case) that the webuser doesn't have write permission on that folder. So you should by able to solve this by providing the full path to a folder that is writeable by the webuser.

ie.

exec("/path/to/binary/wkhtmltopdf http://www.google.com /path/to/pdf1.pdf");

Apart from that I'm not quite sure that wkhtmltopdf can work headless, it could be that it requires a running X server (on a server not running X you could solve this by installing Xvfb and using xvfb-run to run wkhtmltopdf).

wimvds
  • 12,790
  • 2
  • 41
  • 42
  • Well actually I did think of that and I have tried what you mention in your second example with the same results, nothing. Your first snippet returns Array(). As for your second point, from the change log: "No longer requires an XServer to be running (however the X11 client libs must be installed)". It would seem from my poking around that these are installed on my server. Thanks. – Jamie Apr 14 '11 at 15:54
  • Also maybe worth mentioning I can get for example the help info or version info, so there is something working eg. `$out = shell_exec("/path/to/wkhtmlto­pdf --version -"); echo($out);` works fine. – Jamie Apr 14 '11 at 23:02