教你如何使用 PHP 优雅的生成 PDF 和 Image
97

导读:本人初次写博客,有不足之处,请多多指教 。

起因

因为项目中有需求,要动态的生成一些图片,图片的格式要求也比较严格就像是这样的

file

表格中的数据如 单价 数量都是动态的数据, 刚开始准备用 GD库 来操作,后来想想不太现实所以去找了找有没有比较成熟的 php 类库。有不少的类库,可以实现直接生成 PDF 而没有可以直接生成 Image 的扩展包。

后来发现了一个 开源的软件 wkhtmltox 该软件支持读取本地和网络端的网页,直接在本地生成 pdfimagewkhtmltox官方地址

  • 该软件有 Window 版本和 Linux 版本(具体支持详情可以查看其官网)
  • 下载之后需要将可执行文件的路径添加到环境变量中

具体的使用大概是这样的

    $ D:/wktopdf/wkhtmltopdf/bin/wkhtmltoimage --format "jpg" "./1-夏天/夏天.html" "./1-夏天/夏天.jpg"
    $ wkhtmltopdf --format "pdf"  "./1-夏天/夏天.html" "./1-夏天/夏天.pdf"

支持中文路径和中文文件名, 但是用户可不会这种操作,所以需要一些封装(将执行流程抽象化),有一个哥们已经为我们做了,所以不需要我们去造轮子了


PHP实现方式一

KnpLabs/snappy一个基于 wkhtmltoxphp 扩展包 扩展包GitHup地址

使用方式

$ composer require knplabs/knp-snappy
<?php
require __DIR__ . '/vendor/autoload.php';

use Knp\Snappy\Image;

$snappy = new Image('D:/wktopdf/wkhtmltopdf/bin/wkhtmltoimage');                           // 如果你是window环境, 需要将该路径添加到环境变量中
$snappy = new Image(__DIR__ . '/vendor/h4cc/wkhtmltoimage-amd64/bin/wkhtmltoimage-amd64'); // 如果你是linux环境

$str = <<<'EOD'
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<style>
    @font-face {
        font-family: myFirstFont;
        src: url('C:/Users/Administrator/Desktop/snopy/Microsoft Yahei.ttf');
    }

    body {
        font-family: myFirstFont;
    }

</style>
<body>

</body>
</html>
EOD;

$path = __DIR__ .'/我的/';

if (!is_dir($path)) {
    mkdir($path, 0755, true);
}

// 实际生产环境中为了不报错,需要进行异常处理
try {
    // 第一个参数是需要转换的 html
    // 第二个参数是文件保存路径
    $result = $snappy->generateFromHtml($str, $path . '夏天.jpg');
} catch( Exception $e) {
    var_dump($e->getMessage());
}

你也可以从 compoer 中安装需要的 wkhtmltox 依赖,
file

由于 wkhtmltox 是基于 QtWebKit rendering engine, 所以理论上是可以,生成比较复杂的 PDF ,只要你的 Css 写的够好。同时也支持网络协议,可以从网页中生成 PDFImage
如果要引入一些外部的 css 字体 图片 请使用 绝对路径, 生成的 PDF 的大小格式或者分页的使用方式请移步 GitHub地址

重点该扩展包会使用 proc_open 函数 去执行生成的 shell 脚本,所以对生产环境的安全有一定的威胁,最后被砍掉了。


安全的实现方式

由于安全原因,自己做的东西被砍了以后,也尝试了别的方式去实现这个功能,但是都不太如意,因为需要生成的 Image 比较复杂,要么是 css 支持的不是很好,要么就是字体和图片无法引入的错乱。最后想到了在服务端 window的批处理文件 .bat 文件来实现。后来也实现了,可是使用的复杂程度就上去了。
最后在 php 的官方文档中发现了这个

file

查看了一下也是基于 wkhtmltox 的一个 php 的扩展包,于是就动手去实现了一下。

依赖项

  • wkhtmltox 软件 liunx 版本(目前个人只是编译了linux的扩展,如果有兴趣的可以尝试去编译 window版本的)

具体步骤(linux环境)

  1. 首先需要到官网去下载软件 软件下载地址
  2. 扩展需要编译的源码 源码下载地址
  3. 请注意 wkhtmltox 区分操作系统是32位还是64位的
  4. 个人服务器环境是centos7, 使用的 wkhtmltox 的版本是 0.124 0.124版软件包下载地址

开始编译需要的php扩展

git clone https://github.com/krakjoe/wkhtmltox
cd wkhtmltox
phpize
// 这里因为每个人安装环境不一样 /path/to/wkhtmltox/installation 请将这个地址替为wkhtmltox真实的安装路径
 /// PATH 替换为真实的php配置路径
./configure --with-wkhtmltox=/path/to/wkhtmltox/installation --with-php-config = PATH
make
make install
  1. 修改配置文件 ,将生成的 wkhtmltox.so 添加到 php.ini 的配置中,重启php
  2. 安装成功效果

file

  1. 然后就可以 开始愉快的使用这个强大的工具了

HELLO PDF

use wkhtmltox\PDF\Converter as PDFConverter;
use wkhtmltox\PDF\Object as PDFObject;

$converter = new PDFConverter([
    "out" => "test.pdf"
]);

$converter->add(new PDFObject(
    file_get_contents("http://www.baidu.com")));

$converter->convert();

HELLO IMAGE

use wkhtmltox\Image\Converter as ImageConverter;
// 这里第一个参数可以传入 ` html ` 的字符串
$converter = new ImageConverter(null, [
    "fmt" => "png",
    "in" => "http://www.baidu.com",
    "out" => "test.png"
]);

$converter = new ImageConverter($str, [
    "fmt" => "jpg",
    "out" => "test.jpg"
]);
$converter->convert();

这个安全的实现方式,不会使用到一些会威胁到服务器安全的函数

本帖由 Summer 于 4个月前 加精
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
讨论数量: 22

@Summer 大神你好,可以申精吗

4个月前
66

性能如何,刚做完一个需要PDF的需求,用的phpoffice

4个月前

@66 因为是基于第三方的来源软件,速度很快。

4个月前
hainuo

@66 phpoffice 性能太差劲了吧 我之前用的是这个 tcpdf 还凑合吧

4个月前

@hainuo php官方推荐的这个使用起来,比较简单,是以php扩展形式使用的,性能和安全性上都比较高

4个月前

phantomjs了解一下

4个月前

兄弟,错别字~GitHub地址

4个月前

@bestcyt 很强大兄弟^_^, 已改谢谢提醒。

4个月前

@CareyWang 前端很好用的截图包,不知道为什么停止更新了。发个教程?

4个月前
hainuo

@xihanshui 恩 看了 这个必须要安装第三方软件效率上肯定比 tcpdf要好,看了下还支持 win 抽空试一下

4个月前

支持老铁

4个月前

@pigsney 哪一步出错?

4个月前

@xihanshui 输php-config的时候就报这个错误 然后我就分开来写 好像成功了 然后make的时候就报另一个错误

4个月前

@pigsney 试试这样,先清除一下失败的编译信息,然后这样

./configure --with-wkhtmltox=/path/to/wkhtmltox/installation

这个里面路径是你的系统中 wkhtmltox 软件的主目录

4个月前

@xihanshui
试试这样,先清除一下失败的编译信息,然后这样
./configure --with-wkhtmltox=/path/to/wkhtmltox/installation
这个里面路径是你的系统中 wkhtmltox 软件的主目录

4个月前

file
已经安装成功

file
2个wkhtmltox目录下都没有installation,--with-wkhtmltox 没设置,但是可以编译成功

file

file
php -m 显示成功 phpinfo 里却找不到,怎么解决。。。。

4个月前

@feijin_zzz 有没有将扩展名添加到php.ini 文件中,重启php 试试。

4个月前

尝试了很多,最后还是决定用 itext7。
!!! --- 语言只是工具,不要被工具限制住了。

4个月前
joylee109

我想请教一下,使用php 扩展 wkhtmltox.so 来将html 代码转换成图片,能将方法写在控制器当中,然后通过浏览器访问,来触发wkhtmltox.so 将html 代码转换成图片。
我在我自己的本地服务器上面尝试过,发现通过在服务器上面运行脚本的方式: php convert_html_to_image.php 可以快速生成图片,但是通过 http://www.xxx.com/convert_html_to_image.php 不能生成图片,并且,尝试通过url 访问的方式去生成图片的时候,apache 的cpu 占用十分高,容易导致服务器宕机。

3个月前

@joylee109 我使用的也是Apache 没有出现你说的问题 ,可以私聊下

3个月前

太赞了,正好需要

2个月前

  • 请注意单词拼写,以及中英文排版,参考此页
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`, 更多语法请见这里 Markdown 语法
  • 支持表情,使用方法请见 Emoji 自动补全来咯,可用的 Emoji 请见 :metal: :point_right: Emoji 列表 :star: :sparkles:
  • 上传图片, 支持拖拽和剪切板黏贴上传, 格式限制 - jpg, png, gif
  • 发布框支持本地存储功能,会在内容变更时保存,「提交」按钮点击时清空
  请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!