本文概述
你是否曾经尝试使用诸如DomPdf或TCPDF之类的PHP库创建带有复杂图表的PDF文件, 但这样的****任务不是吗?没有太多可用的服务器端免费库来生成图表, 而那些可用的库没有为将其作为图像嵌入到我们的PDF中创建很好的图表。
服务器端生成图表的一种替代方法是使用Javascript(客户端)生成图表。有许多Javascript库可以创建精美的图表, 你可以检索其SVG(或base64图像)并将其返回到服务器, 以将它们作为图像包含在PDF中。听起来不错且功能强大, 但是此解决方案有一个缺点。 SVG会更改, 并会根据用户显示器的分辨率或浏览器窗口的尺寸, 在稍后的PDF中引起尺寸问题。
作为解决方案, 某些Web应用程序将生成一个html视图作为对浏览器的响应(它将呈现你的花式图表), 并且用户将需要使用(并知道如何)浏览器将内容保存(或打印)为PDF 。但是, 作为用户, 你可能只想单击一个按钮即可下载PDF, 选择保存位置, 仅此而已。你不认为对像TCPDF之类的库做一件容易的事吗?
到处都是问题, 但这正是wkhtmltopdf派上用场的地方, 因为你将能够以与在网站中一样的方式编写css, html和javascript(显然有一些最小的限制), 并且PDF看起来很棒。
在本文中, 你将学习如何在symfony 3项目中实现SnappyBundle, 以及如何生成不同方式的PDF。
要求
你需要wkhtmltopdf在系统中可用并且在命令提示符下可访问。 wkhtmltopdf是一个命令行工具, 可使用Qt WebKit渲染引擎将HTML渲染为PDF和各种图像格式。它们完全”无头运行”, 不需要显示或显示服务。
- Windows:你可以在安装区域中下载每种体系结构(x86和x64)的安装程序。尽管稍后你可以在config.yml文件中更改wkhtmltopdf可执行文件的路径, 但是建议将wkhtmltopdf用作系统上的环境变量(如果你不想为wkhtmltopdf创建环境变量, 则可以提供可执行文件的完整路径)。你可以在本文中阅读如何在Windows中创建环境变量。
- Debian / Ubuntu:你可以使用以下命令直接在控制台中从wkhtmltopdf安装发行版:
$ sudo apt-get install wkhtmltopdf
在此处访问wkhtmltopdf的主页以获取更多信息。
1)安装和配置SnappyBundle
Snappy本身就是wkhtmltopdf转换实用程序的PHP(5.3+)包装器。它允许你使用Webkit引擎从html文档生成pdf或图像文件。 KnpSnappyBundle为你的Symfony项目提供了简单的集成。
要在你的项目中安装SnappyBundle, 请执行以下composer命令:
composer require knplabs/knp-snappy-bundle
或手动添加将软件包名称添加到你的composer.json文件中, 然后执行composer install:
{
"require": {
"knplabs/knp-snappy-bundle": "~1.4"
}
}
下载完成后, 启用捆绑软件, 将以下行添加到你的内核中:
$bundles = [
//..//
new Knp\Bundle\SnappyBundle\KnpSnappyBundle(), ];
最后, 你只需要在config.yml文件中添加基本配置, 即可提供并启用wkhtmltopdf的二进制路径。
请注意, 如前所述, SnappyBundle需要wkhtmltopdf才能运行, 因此在使用config.yml的二进制选项之前, 我们需要提供wkhtmltopdf可执行文件的完整路径, 否则你将面临最常见的错误之一:
退出状态代码” 1″表示出了点问题:stderr:”” stdout:””
Windows中的二进制路径
使用wkhtmltopdf的默认安装程序(和默认安装设置), 主分区的程序文件中应该有一个文件夹wkhtmltopdf / bin, 其中包含wkhtmltopdf的可执行文件, 因此你只需要提供以下示例的路径即可。
但是, 如果你使用的是自定义安装, 则只需使用二进制属性中包含wkhtmltopdf可执行文件的新安装更改路径。
# Windows configuration
knp_snappy:
pdf:
enabled: true
# If you have wkhtmltopdf as an environment variable you don't need to provide the
# full path to the executable, use it in the same way as you use in the console
#binary: "wkhtmltopdf"
binary: "\"C:\\Program Files\\wkhtmltopdf\\bin\\wkhtmltopdf.exe\""
options: []
image:
enabled: true
binary: "\"C:\\Program Files\\wkhtmltopdf\\bin\\wkhtmltoimage.exe\""
options: []
Linux / Unix中的二进制路径, 例如
如果使用apt-get方法安装了wkhtmltopdf, 则路径可能是:
# app/config/config.yml
knp_snappy:
pdf:
enabled: true
binary: /usr/local/bin/wkhtmltopdf
options: []
image:
enabled: true
binary: /usr/local/bin/wkhtmltoimage
options: []
如何更改PDF生成设置
你可以在config.yml文件中默认更改设置:
# config.yml
knp_snappy:
pdf:
enabled: true
binary: "wkhtmltopdf"
options:
no-outline: true
page-size: LETTER
# Recommended to set UTF-8 as default encoding :)
encoding: UTF-8
或者使用PHP和snappy的setOption方法在控制器(或服务等)中进行动态分析:
$snappy = $this->get('knp_snappy.pdf');
$snappy->setOption('no-outline', true);
$snappy->setOption('page-size', 'LETTER');
$snappy->setOption('encoding', 'UTF-8');
你可以在本文档中看到可用于wkhtmltopdf的所有选项的完整列表。
更改生成PDF的缓存路径
Snappy默认情况下使用sys_get_temp_dir()方法来获取系统的临时文件文件夹以保存PDF, 但是你可以使用secondary_folder属性更改要更改的路径:
# app/config/config.yml
knp_snappy:
temporary_folder: %kernel.cache_dir%/snappy
上一个示例将目标放在SF3项目的缓存文件夹中的文件夹(var / cache / snappy)。
2)例子
从Web网址渲染PDF
以下示例将以PDF格式显示我们的代码世界首页:
<?php
namespace sandboxBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
class DefaultController extends Controller
{
public function indexAction()
{
$snappy = $this->get('knp_snappy.pdf');
$filename = 'myFirstSnappyPDF';
$url = 'http://ourcodeworld.com';
return new Response(
$snappy->getOutput($url), 200, array(
'Content-Type' => 'application/pdf', 'Content-Disposition' => 'inline; filename="'.$filename.'.pdf"'
)
);
}
}
从项目URL渲染PDF(symfony路由)
在此示例中有2条路线:
sandbox_homepage:
path: /
defaults: { _controller: sandboxBundle:Default:index }
sandbox_pdfexample:
path: /pdf-example
defaults: { _controller: sandboxBundle:Default:pdf }
和控制器:
<?php
namespace sandboxBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
class DefaultController extends Controller
{
public function indexAction()
{
return $this->render('sandboxBundle:Default:index.html.twig', [
]);
}
/**
* Render in a PDF the sandbox_homepage URL
* @return Response
*/
public function pdfAction()
{
$snappy = $this->get('knp_snappy.pdf');
$filename = 'myFirstSnappyPDF';
// use absolute path !
$pageUrl = $this->generateUrl('sandbox_homepage', array(), UrlGeneratorInterface::ABSOLUTE_URL);
return new Response(
$snappy->getOutput($pageUrl), 200, array(
'Content-Type' => 'application/pdf', 'Content-Disposition' => 'inline; filename="'.$filename.'.pdf"'
)
);
}
}
注意:使用当前的Request对象自动检测生成绝对URL时使用的主机。从Web上下文外部(例如在控制台命令中)生成绝对URL时, 此操作无效。请参阅如何从控制台生成URL, 以了解如何解决此问题。
从twig视图的HTML渲染PDF
<?php
namespace sandboxBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
class DefaultController extends Controller
{
public function indexAction()
{
$snappy = $this->get('knp_snappy.pdf');
$html = $this->renderView('sandboxBundle:Default:template.html.twig', array(
//..Send some data to your view if you need to //
));
$filename = 'myFirstSnappyPDF';
return new Response(
$snappy->getOutputFromHtml($html), 200, array(
'Content-Type' => 'application/pdf', 'Content-Disposition' => 'inline; filename="'.$filename.'.pdf"'
)
);
}
}
返回PDF响应以便在浏览器中查看
<?php
namespace sandboxBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
class DefaultController extends Controller
{
public function indexAction()
{
$snappy = $this->get('knp_snappy.pdf');
$html = '<h1>Hello</h1>';
$filename = 'myFirstSnappyPDF';
return new Response(
$snappy->getOutputFromHtml($html), 200, array(
'Content-Type' => 'application/pdf', 'Content-Disposition' => 'inline; filename="'.$filename.'.pdf"'
)
);
}
}
以附件形式返回PDF响应(下载响应)
<?php
namespace sandboxBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
class DefaultController extends Controller
{
public function indexAction()
{
$snappy = $this->get('knp_snappy.pdf');
$html = '<h1>Hello</h1>';
$filename = 'myFirstSnappyPDF';
return new Response(
$snappy->getOutputFromHtml($html), 200, array(
'Content-Type' => 'application/pdf', 'Content-Disposition' => 'attachment; filename="'.$filename.'.pdf"'
)
);
}
}
wkhtmltopdf主要功能(和优点)的基本示例
只需按照你在浏览器中的方式工作, wkhtmltopdf将负责将其转换为pdf。在此示例中, 我们将生成具有一些基本功能的PDF, 例如javascript, svg等的用法。
<h1>{{title}}</h1>
<p>This is my awesome first PDF generated using Snappy in my Symfony 3 project.</p>
<p>UTF-8 Test : κ?σμε</p>
<p>Image : </p><br>
<img height="200" src="http://ourcodeworld.com/resources/img/ocw-empty.png"/>
<p>SVG Example : </p><br>
<div>
<!-- Do not forget to give width and height to your svg
use PLAIN SVG directly (<svg>content</svg>)
Tiger SVG EXAMPLE : https://upload.wikimedia.org/wikipedia/commons/f/fd/Ghostscript_Tiger.svg
-->
</div>
<p>Canvas Example with Javascript: </p><br>
<div>
<canvas id="myCanvas" width="300" height="200"/>
</div>
<hr>
<span id="dinamic-content"></span>
<script>
document.getElementById("dinamic-content").innerHTML = 'This string has been appended using javascript';
// Draw circle on canvas
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.beginPath();
ctx.arc(100, 75, 50, 0, 2*Math.PI);
ctx.stroke();
</script>
我们将使用一个简单的控制器将生成的PDF返回到浏览器:
<?php
namespace sandboxBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
class DefaultController extends Controller
{
public function indexAction()
{
$snappy = $this->get('knp_snappy.pdf');
$html = $this->renderView('sandboxBundle:Default:template.html.twig', array(
'title' => 'Hello World !'
));
$filename = 'myFirstSnappyPDF';
return new Response(
$snappy->getOutputFromHtml($html), 200, array(
'Content-Type' => 'application/pdf', 'Content-Disposition' => 'inline; filename="'.$filename.'.pdf"'
)
);
}
}
PDF输出应如下所示:
结论
- 你需要在计算机上安装wkhtmltopdf。 Snappy只是一个包装器, 使用几行PHP即可使你轻松轻松地生成PDF。如果你不是安装设置的朋友, 则可以在项目中使用wkhtmltopdf作为作曲者依赖项的”便携式”版本。
- wkhtmltopdf允许你从Web url(或纯html)创建图像(屏幕快照), 并且SnappyBundle附带了包装器, 请在文档中详细了解此功能。
- 多亏了wkhtmltopdf, 你可以使用Javascript修改HTML内容以生成PDF, 这非常方便, 可以使用客户端代码(如Highcharts, D3.js等库)在PDF中显示图表或图形。
玩得开心 !
评论前必须登录!
注册