我使用安装了wkhtmltopdf
sudo apt-get install wkhtmltopdf
我有一个为此生成命令的 php 脚本。
它生成的一个例子是
wkhtmltopdf 'http://stackoverflow.com' "/tmp/Stack Overflow.pdf" --orientation Portrait --page-size A1 --zoom 1
在终端中运行时运行良好。
但是,使用shell_exec()
它运行时似乎没有效果。
请注意,调用echo shell_exec('wkhtmltopdf --version -');
输出版本信息,所以有些东西正在工作......
实际代码:
class pdf
{
protected $contents_url = null;
protected $local_html_file = null;
protected $contents_are_local = false;
protected $tmp_path = '/tmp/';
protected $exec_path = '/usr/bin/wkhtmltopdf';
protected $cmd = null;
protected $orientation = 'Portrait';
protected $size = pdf::A4;
protected $toc = false;
protected $color = true;
protected $title = null;
protected $auth = array('enable' => false, 'user' => null, 'pass' => null);
protected $headers = array();
protected $cookies = array();
protected $post = array();
protected $replace = array();
protected $forms = false;
protected $zoom = 1;
protected $javascript = true;
protected $footer = array('center' => null, 'left' => null, 'right' => null, 'font' => null, 'size' => null,
'spacing' => null, 'html' => null, 'line' => null);
protected $heading = array('center' => null, 'left' => null, 'right' => null, 'font' => null, 'size' => null,
'spacing' => null, 'html' => null, 'line' => null, 'default' => null);
//these are the supported paper sizes, although they don't do much, using the const's means that if you use
//an unsupported size php will throw an error
const A0 = 'A1';
const A1 = 'A1';
const A2 = 'A2';
const A3 = 'A3';
const A4 = 'A4';
const A5 = 'A5';
const A6 = 'A6';
const A7 = 'A7';
const A8 = 'A8';
const A9 = 'A9';
const B0 = 'B1';
const B1 = 'B1';
const B2 = 'B2';
const B3 = 'B3';
const B4 = 'B4';
const B5 = 'B5';
const B6 = 'B6';
const B7 = 'B7';
const B8 = 'B8';
const B9 = 'B9';
const B10 = 'B10';
const C5E = 'C5E';
const Comm10E = 'Comm10E';
const DLE = 'DLE';
const Executive = 'Executive';
const Folio = 'Folio';
const Ledger = 'Ledger';
const Legal = 'Legal';
const Letter = 'Letter';
const Tabloid = 'Tabloid';
public function __construct($contents = null)
{
error_reporting(E_ALL);
ini_set('display_errors', 1);
if ($contents != null)
$this->contents($contents);
}
public function contents($contents = 'http://example.com')
{
if (stripos($contents, 'http://') === 0 || stripos($contents, 'https://') === 0) {
$this->contents_url = $contents;
$this->contents_are_local = false;
return $this;
}
if ($this->local_html_file == null)
$this->local_html_file = $this->tmp_path . rand(0, 1000) . md5(microtime()) . '.html';
if (!file_put_contents($this->local_html_file, $contents)) {
trigger_error('Failed to write contents to file');
return false;
}
$this->contents_are_local = true;
$this->contents_url = $this->local_html_file;
return $this;
}
//set the path to a writeable folder
public function tmp($path = '/tmp/')
{
$this->tmp_path = $path;
return $this;
}
//set the path to the executable
public function executable($path = 'wkhtmltopdf-i386')
{
$this->exec_path = $path;
return $this;
}
//set the orientation of the pdf file
public function orient($orientation = 'Portrait')
{
$this->orientation = ucfirst($orientation);
return $this;
}
//set the size of the page
public function size($size = pdf::A4)
{
$this->size = ucfirst($size);
return $this;
}
//use table of contents?
public function toc($create_toc = false)
{
$this->toc = $create_toc;
return $this;
}
//create color pdf?
public function color($use_color = true)
{
$this->color = $use_color;
return $this;
}
//alias for color, damn americans!
public function colour($use_colour = true)
{
return $this->color($use_colour);
}
//set the title. by default this is the document title
public function title($title = null)
{
$this->title = $title;
}
//set a custom header for accessing the page
public function header($key, $value = null)
{
if ($value == null)
unset($this->headers[$key]);
else
$this->headers[$key] = $value;
return $this;
}
//set a custom cookie for accessing the page
public function cookie($key, $value = null)
{
if ($value == null)
unset($this->cookies[$key]);
else
$this->cookies[$key] = $value;
return $this;
}
//set a custom post field for accessing the page
public function post($key, $value = null)
{
if ($value == null)
unset($this->cookies[$key]);
else
$this->post[$key] = $value;
return $this;
}
//used to set a custom replace string in the header/footer
public function replace($what, $with = null)
{
if ($with == null)
unset($this->replace[$what]);
else
$this->replace[$what] = $with;
return $this;
}
//do you want to convert html forms to pdf forms?
public function forms($enable = true)
{
$this->forms = $enable;
return $this;
}
public function zoom($level = 1)
{
$this->zoom = $level;
}
public function javascript($enable = true){
$this->javascript = $enable;
}
//used to request the page with basic http auth
public function authenticate($username = null, $password = null)
{
if ($username == null && $password == null) {
$this->auth['enable'] == false;
return $this;
}
if (($username == null && $password != null) || ($username != null && $password == null)) {
trigger_error('Username and Password must be set to use authentication, (call function with no parameters to disabled authentication)');
return $this;
}
$disallowed = array(' ', '/', '\'', '"', '\\');
foreach ($disallowed as $char) {
if (stripos($username . $password, $char) !== false) {
trigger_error('Invalid characters in authentication settings');
return $this;
}
}
$this->auth['enabled'] = true;
$this->auth['user'] = $username;
$this->auth['pass'] = $password;
return $this;
}
//used to set all the footer options
public function footer($what = null, $value = null)
{
//support for array to be passed
if(is_array($what)){
foreach($what as $key => $val)
$this->footer($key, $val);
return $this;
}
//handler to clear footer
if($what == null){
foreach($this->footer as &$val)
$val = null;
return $this;
}
switch (strtolower($what)) {
//centered footer text
case 'center':
$this->footer['center'] = $value;
return $this;
//left aligned footer text
case 'left':
$this->footer['left'] = $value;
return $this;
//right aligned footer text
case 'right':
$this->footer['right'] = $value;
return $this;
//footer font name (default Arial)
case 'font':
case 'font-name':
$this->footer['font'] = $value;
return $this;
//footer font size
case 'size':
case 'font-size':
$this->footer['size'] = $value;
return $this;
//url if you wish an html page to be used as the footer
case 'html':
foreach($this->footer as &$val) $val = null;
$this->footer['html'] = $value;
return $this;
//display a line above the footer
case 'line':
$this->footer['line'] = $value;
return $this;
//spacing between footer and content in mm
case 'spacing';
$this->footer['spacing'] = $value;
return $this;
default:
trigger_error('Invalid options passed to footer');
return $this;
}
}
//documentation same as footer
public function heading($what = null, $value = null)
{
//support for array to be passed
if(is_array($what)){
foreach($what as $key => $val)
$this->heading($key, $val);
return $this;
}
if($what != 'default')
$this->heading['default'] == null;
//handler to clear footer
if($what == null){
foreach($this->footer as &$val)
$val = null;
return $this;
}
switch (strtolower($what)) {
//centered heading text
case 'center':
$this->heading['center'] = $value;
return $this;
//left aligned heading text
case 'left':
$this->heading['left'] = $value;
return $this;
//right aligned heading text
case 'right':
$this->heading['right'] = $value;
return $this;
//heading font name (default Arial)
case 'font':
case 'font-name':
$this->heading['font'] = $value;
return $this;
//heading font size
case 'size':
case 'font-size':
$this->heading['size'] = $value;
return $this;
//url if you wish an html page to be used as the heading
case 'html':
foreach($this->heading as &$val) $val = null;
$this->heading['html'] = $value;
return $this;
//display a line below the heading
case 'line':
$this->heading['line'] = $value;
return $this;
//spacing between heading and content in mm
case 'spacing';
$this->heading['spacing'] = $value;
return $this;
//used to enable the default heading
case 'default':
foreach($this->heading as &$val) $val = null;
$this->heading['default'] = $value;
return $this;
default:
trigger_error('Invalid options passed to heading');
return $this;
}
}
//function to generate pdf, saveFile is used to change where the file is saved to
//if saveFile is not set, a file will be created in the tmp directory
public function generate($mode = 'return|clean|remove', $saveFile = null, $use_tmp = false)
{
//if (!file_exists($this->exec_path))
// trigger_error('Could not load executable');
$input = escapeshellarg($this->contents_url);
$output = ($saveFile == null ? $this->tmp_path . rand(0, 1000) . md5(microtime()) . '.pdf' : ($use_tmp
? $this->tmp_path : '') . $saveFile . '.pdf');
$filename = end(explode('/', $output));
if (!$this->execute($input, $output)) {
trigger_error('Failed to create pdf');
return false;
}
$pdf = file_get_contents($output);
$actions = explode('|', str_replace(' ', '', $mode));
//-------------------------
//VALID ACTION SETS
//-------------------------
//using a non-valid action
//set will cause un-intended
//consequences
//-----------------------
//DOWNLOAD
//-----------------------
//RETURN
//-----------------------
//SAVE
//-----------------------
//EMBED
//-------------------------
//REMOVE + DOWNLOAD
//-------------------------
//REMOVE + RETURN
//-----------------------
//REMOVE + EMBED
//-------------------------
//CLEAN + DOWNLOAD
//-------------------------
//CLEAN + RETURN
//-------------------------
//CLEAN + SAVE
//-----------------------
//CLEAN + EMBED
//-------------------------
//CLEAN + REMOVE + DOWNLOAD
//-------------------------
//CLEAN + REMOVE + RETURN
//-------------------------
//CLEAN + REMOVE + EMBED
//-----------------------
//CLEAN: remove the html file
if (in_array('clean', $actions) && $this->local_html_file != null)
unlink($this->local_html_file);
//REMOVE: remove the pdf file
if (in_array('remove', $actions))
unlink($output);
//SAVE: don't delete the pdf and return the path to it
if (in_array('save', $actions))
return $output;
//RETURN: return the pdf as a string
if (in_array('return', $actions))
return $pdf;
//DOWNLOAD: generate a download request
if (in_array('download', $actions)) {
header('Content-Type: application/pdf');
header('Content-Length: ' . strlen($pdf));
header('Content-Disposition: attachment; filename="' . $filename . '"');
header('Cache-Control: private, max-age=0, must-revalidate');
header('Pragma: public');
ini_set('zlib.output_compression', '0');
die($pdf);
}
//EMBED: show the pdf
if (in_array('embed', $actions)) {
header('Content-Type: application/pdf');
header('Content-Length: ' . strlen($pdf));
header('Content-Disposition: inline; filename="' . $filename . '"');
header('Cache-Control: private, max-age=0, must-revalidate');
header('Pragma: public');
ini_set('zlib.output_compression', '0');
die($pdf);
}
trigger_error('No return type for pdf specified');
}
private function execute($input, $output)
{
$this->cmd = $this->exec_path;
$this->cmd .= ' ' . $input;
$this->cmd .= ' "' . $output.'"';
$this->cmd .= ' --orientation ' . $this->orientation;
$this->cmd .= ' --page-size ' . $this->size;
$this->cmd .= ' --zoom ' . $this->zoom;
$this->cmd .= ($this->toc ? ' --toc' : '');
$this->cmd .= ($this->javascript ? '' : ' --disable-javascript');
$this->cmd .= ($this->color ? '' : ' --grayscale');
$this->cmd .= ($this->forms ? ' --forms' : '');
$this->cmd .= ($this->title != null ? ' --title "' . $this->title . '"' : '');
$this->cmd .= ($this->heading['center'] == null ? '' : ' --header-center "'.$this->heading['center'].'"');
$this->cmd .= ($this->heading['left'] == null ? '' : ' --header-left "'.$this->heading['left'].'"');
$this->cmd .= ($this->heading['right'] == null ? '' : ' --header-right "'.$this->heading['right'].'"');
$this->cmd .= ($this->heading['font'] == null ? '' : ' --header-font-name "'.$this->heading['font'].'"');
$this->cmd .= ($this->heading['size'] == null ? '' : ' --header-font-size '.$this->heading['size']);
$this->cmd .= ($this->heading['line'] == null ? '' : ' --header-line');
$this->cmd .= ($this->heading['spacing'] == null ? '' : ' --header-spacing '.$this->heading['spacing']);
$this->cmd .= ($this->heading['html'] == null ? '' : ' --header-html '.$this->heading['html']);
$this->cmd .= ($this->heading['default'] == null ? '' : ' --default-header');
$this->cmd .= ($this->footer['center'] == null ? '' : ' --footer-center "'.$this->footer['center'].'"');
$this->cmd .= ($this->footer['left'] == null ? '' : ' --footer-left "'.$this->footer['left'].'"');
$this->cmd .= ($this->footer['right'] == null ? '' : ' --footer-right "'.$this->footer['right'].'"');
$this->cmd .= ($this->footer['font'] == null ? '' : ' --footer-font-name "'.$this->footer['font'].'"');
$this->cmd .= ($this->footer['size'] == null ? '' : ' --footer-font-size '.$this->footer['size']);
$this->cmd .= ($this->footer['line'] == null ? '' : ' --footer-line');
$this->cmd .= ($this->footer['spacing'] == null ? '' : ' --footer-spacing '.$this->footer['spacing']);
$this->cmd .= ($this->footer['html'] == null ? '' : ' --footer-html '.$this->footer['html']);
if ($this->auth['enable']) {
$this->cmd .= ' --username ' . $this->auth['user'];
$this->cmd .= ' --password ' . $this->auth['pass'];
}
foreach ($this->headers as $key => $value)
$this->cmd .= ' --custom-header ' . $key . ' ' . $value;
foreach ($this->cookies as $key => $value)
$this->cmd .= ' --cookie ' . $key . ' ' . $value;
foreach ($this->post as $key => $value)
$this->cmd .= ' --post ' . $key . ' ' . $value;
foreach ($this->replace as $key => $value)
$this->cmd .= ' --replace ' . $key . ' "' . $value.'"';
//debug flag
if(isset($_GET['show_convert_cmd']) && $_GET['show_convert_cmd'])
die($this->cmd);
//todo: find all possible return values on correct function
//todo: for now we will just spit out true for everything
shell_exec($this->cmd);
return true;
}
}
?>
演示页面
if (!isset($_GET['example'])) {
$examples = array(
'DEFAULT SETTINGS: HTML STRING',
'DEFAULT SETTINGS: RETURN',
'DEFAULT SETTINGS: DOWNLOAD',
'DEFAULT SETTINGS: SAVE',
'SETTING PAPER SIZE: A0',
'USING TABLE OF CONTENTS',
'GRAYSCALE PDF GENERATION',
'SETTING ORIENTATION: LANDSCAPE',
'BASIC HTTP AUTHENTICATION',
'SETTING CUSTOM HTTP HEADERS',
'SETTING COOKIES',
'ENABLE FORM CONVERSION',
'HEADERS AND FOOTERS: ENABLE DEFAULT PDF HEADER',
'HEADERS AND FOOTERS: SET LEFT CONTENT AND A CUSTOM REPLACEMENT VALUE',
'HEADERS AND FOOTERS: SET LEFT AND RIGHT CONTENT USING MULTIPLE CALLS',
'HEADERS AND FOOTERS: SET LEFT AND RIGHT CONTENT USING AN ARRAY',
'DISABLE JAVASCRIPT',
'SETTING ZOOM LEVEL'
);
foreach ($examples as $id => $example) {
echo '<a href="?example=' . $id . '">' . $example . '</a><hr />';
}
die();
}
require_once('class.php');
$html = '<!doctype html><html><head><title>Lol Title</title><link rel="stylesheet" href="http://doc.trolltech.com/4.6/classic.css"/></head><body><h2>Lols</h2><table class="valuelist"><tr><th>Lol</th><th>Again</th></tr><tr><td>First</td><td>Second</td></tr></table><h2>Form</h2><form><input value="input" /><input type="checkbox" /><input type="checkbox" checked="checked" /><input type="submit" value="Submit" /></form></body></html>';
$html_pdf_name = 'HTML Example';
$url = 'http://stackoverflow.com';
$url_pdf_name = 'Stack Overflow';
switch ($_GET['example']) {
//--------------------------------------
//EXAMPLE: DEFAULT SETTINGS: HTML STRING
//--------------------------------------
case 0:
$pdf = new pdf($html);
$pdf->generate('remove|clean|embed', $html_pdf_name, true);
break;
//--------------------------------------
//EXAMPLE: DEFAULT SETTINGS: RETURN
//--------------------------------------
case 1:
$pdf = new pdf($url);
$pdf_contents = $pdf->generate('remove|clean|return', $url_pdf_name, true);
echo $pdf_contents;
break;
//--------------------------------------
//EXAMPLE: DEFAULT SETTINGS: DOWNLOAD
//--------------------------------------
case 2:
$pdf = new pdf($url);
$pdf->generate('remove|clean|download', $url_pdf_name, true);
break;
//--------------------------------------
//EXAMPLE: DEFAULT SETTINGS: SAVE
//--------------------------------------
case 3:
$pdf = new pdf($url);
echo $pdf->generate('clean|save', $url_pdf_name, true);
break;
//--------------------------------------
//EXAMPLE: SETTING SIZE: A0
//--------------------------------------
case 4:
$pdf = new pdf($url);
$pdf->size(pdf::A0)->generate('remove|clean|embed', $url_pdf_name, true);
break;
//--------------------------------------
//EXAMPLE: TABLE OF CONTENTS
//--------------------------------------
case 5:
$pdf = new pdf($url);
$pdf->toc(true)->generate('remove|clean|embed', $url_pdf_name, true);
break;
//--------------------------------------
//EXAMPLE: GRAYSCALE
//--------------------------------------
case 6:
$pdf = new pdf($url);
$pdf->color(false)->generate('remove|clean|embed', $url_pdf_name, true);
break;
//--------------------------------------
//EXAMPLE: ORIENTATION: LANDSCAPE
//--------------------------------------
case 7:
$pdf = new pdf($url);
$pdf->orient('Landscape')->generate('remove|clean|embed', $url_pdf_name, true);
break;
//--------------------------------------
//EXAMPLE: AUTHENTICATION: BASIC HTTP AUTH
//--------------------------------------
case 8:
$pdf = new pdf($url);
$pdf->authenticate('username', 'password')->generate('remove|clean|embed', $url_pdf_name, true);
break;
//--------------------------------------
//EXAMPLE: HEADERS: SETTING A CUSTOM HEADER
//--------------------------------------
case 9:
$pdf = new pdf($url);
$pdf->header('key', 'value')->generate('remove|clean|embed', $url_pdf_name, true);
break;
//--------------------------------------
//EXAMPLE: COOKIES: SETTING A CUSTOM COOKIE
//--------------------------------------
case 10:
$pdf = new pdf($url);
$pdf->cookie('key', 'value')->generate('remove|clean|embed', $url_pdf_name, true);
break;
//--------------------------------------
//EXAMPLE: FORMS: ENABLE FORMS CONVERSION
//--------------------------------------
case 11:
$pdf = new pdf($html);
$pdf->forms(true)->generate('remove|clean|embed', $html_pdf_name, true);
break;
//--------------------------------------
//EXAMPLE: HEADERS AND FOOTERS: ENABLE DEFAULT HEADER
//there are a crap load more header and footer settings, look in the code and it should be obvious!
//--------------------------------------
case 12:
$pdf = new pdf($url);
$pdf->heading('default', true)->generate('remove|clean|embed', $url_pdf_name, true);
break;
//--------------------------------------
//EXAMPLE: HEADERS AND FOOTERS: SET THE LEFT FOOTER CONTENT, AND A CUSTOM REPLACE FOR IT
//there are a crap load more header and footer settings, look in the code and it should be obvious!
//--------------------------------------
case 13:
$pdf = new pdf($url);
$pdf->heading('left', 'Page [page] of [topage] by [myuser]')->replace('myuser', 'My Users Name')->generate('remove|clean|embed', $url_pdf_name, true);
break;
//--------------------------------------
//EXAMPLE: HEADERS AND FOOTERS: SET THE LEFT AND RIGHT FOOTER CONTENT, USING MULTIPLE CALLS
//there are a crap load more header and footer settings, look in the code and it should be obvious!
//--------------------------------------
case 14:
$pdf = new pdf($url);
$pdf->heading('left', 'Page [page] of [topage]')->heading('right', '[time]')->generate('remove|clean|embed', $url_pdf_name, true);
break;
//--------------------------------------
//EXAMPLE: HEADERS AND FOOTERS: SET THE LEFT AND RIGHT FOOTER CONTENT, USING ARRAY
//there are a crap load more header and footer settings, look in the code and it should be obvious!
//--------------------------------------
case 15:
$heading = array(
'left' => 'Page [page] of [topage]',
'right' => '[time]'
);
$pdf = new pdf($url);
$pdf->heading($heading)->generate('remove|clean|embed', $url_pdf_name, true);
break;
//--------------------------------------
//EXAMPLE: DISABLE JAVASCRIPT
//--------------------------------------
case 16:
$pdf = new pdf($url);
$pdf->javascript(false)->generate('remove|clean|embed', $url_pdf_name, true);
break;
//--------------------------------------
//EXAMPLE: SETTING ZOOM
//--------------------------------------
case 17:
$pdf = new pdf($url);
$pdf->zoom(5)->generate('remove|clean|embed', $url_pdf_name, true);
break;
}