如何在Symfony 3中使用SnappyBundle(wkhtmltopdf)从HTML创建PDF

本文概述

  • 要求
  • 1)安装和配置SnappyBundle
  • 2)例子
  • 结论
你是否曾经尝试使用诸如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的可执行文件, 因此你只需要提供以下示例的路径即可。
【如何在Symfony 3中使用SnappyBundle(wkhtmltopdf)从HTML创建PDF】但是, 如果你使用的是自定义安装, 则只需使用二进制属性中包含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格式显示我们的代码世界首页:
< ?phpnamespace 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 }

和控制器:
< ?phpnamespace 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
< ?phpnamespace 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响应以便在浏览器中查看
< ?phpnamespace 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响应(下载响应)
< ?phpnamespace 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返回到浏览器:
< ?phpnamespace 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输出应如下所示:
如何在Symfony 3中使用SnappyBundle(wkhtmltopdf)从HTML创建PDF

文章图片
结论
  • 你需要在计算机上安装wkhtmltopdf。 Snappy只是一个包装器, 使用几行PH??P即可使你轻松轻松地生成PDF。如果你不是安装设置的朋友, 则可以在项目中使用wkhtmltopdf作为作曲者依赖项的” 便携式” 版本。
  • wkhtmltopdf允许你从Web url(或纯html)创建图像(屏幕快照), 并且SnappyBundle附带了包装器, 请在文档中详细了解此功能。
  • 多亏了wkhtmltopdf, 你可以使用Javascript修改HTML内容以生成PDF, 这非常方便, 可以使用客户端代码(如Highcharts, D3.js等库)在PDF中显示图表或图形。
玩得开心 !

    推荐阅读