教你如何使用 PHP 优雅的生成 PDF 和 Image
导读:本人初次写博客,有不足之处,请多多指教 。
起因
因为项目中有需求,要动态的生成一些图片,图片的格式要求也比较严格就像是这样的
表格中的数据如 单价 数量都是动态的数据, 刚开始准备用 GD库
来操作,后来想想不太现实所以去找了找有没有比较成熟的 php
类库。有不少的类库,可以实现直接生成 PDF
而没有可以直接生成 Image
的扩展包。
后来发现了一个 开源的软件 wkhtmltox
该软件支持读取本地和网络端的网页,直接在本地生成 pdf
或 image
。wkhtmltox官方地址
- 该软件有 Window 版本和 Linux 版本(具体支持详情可以查看其官网)
- 下载之后需要将可执行文件的路径添加到环境变量中
具体的使用大概是这样的
$ D:/wktopdf/wkhtmltopdf/bin/wkhtmltoimage --format "jpg" "./1-夏天/夏天.html" "./1-夏天/夏天.jpg"
$ wkhtmltopdf --format "pdf" "./1-夏天/夏天.html" "./1-夏天/夏天.pdf"
支持中文路径和中文文件名, 但是用户可不会这种操作,所以需要一些封装(将执行流程抽象化),有一个哥们已经为我们做了,所以不需要我们去造轮子了。
PHP实现方式一
KnpLabs/snappy
一个基于 wkhtmltox
的 php
扩展包 扩展包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
依赖,
由于
wkhtmltox
是基于QtWebKit rendering engine
, 所以理论上是可以,生成比较复杂的Css
写的够好。同时也支持网络协议,可以从网页中生成Image
。
如果要引入一些外部的css
字体
图片
请使用 绝对路径, 生成的
重点该扩展包会使用 proc_open
函数 去执行生成的 shell
脚本,所以对生产环境的安全有一定的威胁,最后被砍掉了。
安全的实现方式
由于安全原因,自己做的东西被砍了以后,也尝试了别的方式去实现这个功能,但是都不太如意,因为需要生成的
Image
比较复杂,要么是css
支持的不是很好,要么就是字体和图片无法引入的错乱。最后想到了在服务端window
的批处理文件.bat
文件来实现。后来也实现了,可是使用的复杂程度就上去了。
最后在php
的官方文档中发现了这个
查看了一下也是基于 wkhtmltox
的一个 php 的扩展包,于是就动手去实现了一下。
依赖项
wkhtmltox
软件 liunx 版本(目前个人只是编译了linux的扩展,如果有兴趣的可以尝试去编译 window版本的)
具体步骤(linux环境)
- 首先需要到官网去下载软件 软件下载地址
- 扩展需要编译的源码 源码下载地址
- 请注意
wkhtmltox
区分操作系统是32位还是64位的 - 个人服务器环境是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
- 修改配置文件 ,将生成的
wkhtmltox.so
添加到php.ini
的配置中,重启php - 安装成功效果
- 然后就可以 开始愉快的使用这个强大的工具了
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();
这个安全的实现方式,不会使用到一些会威胁到服务器安全的函数
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: