friendsofcake/cakepdf

CakePHP 插件,用于创建和/或渲染 PDF,支持多个 PDF 引擎。

安装数: 1,635,908

依赖项: 6

建议者: 0

安全: 0

星星: 373

关注者: 40

分支: 183

开放问题: 6

类型:cakephp-plugin

5.0.0 2023-10-03 08:38 UTC

README

Build Status Total Downloads License

包含 CakePdf 库的插件,使用 PDF 引擎将 HTML 转换为 PDF。

插件中包含的引擎

  • DomPdf (^2.0)
  • Mpdf (^8.0.4)
  • Tcpdf (^6.3)
  • WkHtmlToPdf 推荐引擎

社区维护的引擎

要求

安装

使用 Composer

composer require friendsofcake/cakepdf

CakePdf 不包含任何支持的 PDF 引擎,您需要自己安装您打算使用的引擎。

推荐 wkhtmltopdf 引擎的包可以从 https://wkhtmltopdf.org/downloads.html 下载。DomPdf、Mpdf 和 Tcpdf 可以通过 composer 使用以下命令之一安装:

composer require dompdf/dompdf
composer require tecnickcom/tcpdf
composer require mpdf/mpdf

设置

使用 CakePHP 控制台加载插件

./bin/cake plugin load CakePdf

如果您打算使用 PDF 视图功能,该功能会自动渲染并返回 PDF 以发送到浏览器,您还应该在您的 config/routes.php 文件中注册 pdf 扩展。

$routes->scope('/', function (\Cake\Routing\RouteBuilder $routes) {
    $routes->setExtensions(['pdf']);
    // ...
});

有关进一步设置的信息,请参阅使用部分。

配置

使用 Configure::write('CakePdf', $config); 或在控制器中使用视图构建器设置名为 pdfConfig 的视图选项(仅在用于 PdfView 时)。您需要定义至少 $config['engine']。直接使用 CakePdf 时,您也可以将配置数组传递给构造函数。引擎的值应采用 Plugin.ClassName 格式,不带引擎后缀。

配置选项

  • engine: 使用的引擎(必需),或引擎配置选项的数组
    • className: 要使用的引擎类
    • binary: 要使用的二进制文件(仅限 wkhtmltopdf)
    • cwd: 当前工作目录(仅限 wkhtmltopdf)
    • options: 引擎特定选项。目前用于以下引擎
      • WkHtmlToPdfEngine: 选项作为 CLI 参数传递
      • TexToPdfEngine: 选项作为 CLI 参数传递
      • DomPdfEngine: 选项传递给 Dompdf 类的构造函数
      • MpdfEngine: 选项传递给 Mpdf 类的构造函数
  • crypto: 要使用的加密引擎,或加密配置选项的数组
    • className: 要使用的加密类
    • binary: 要使用的二进制文件
  • pageSize: 更改默认大小,默认为 A4
  • orientation: 更改默认方向,默认为纵向
  • margin: 包含键:bottom、left、right、top 和其值的数组或边距
  • title: 文档标题
  • delay: 在渲染 PDF 之前等待的毫秒数
  • windowStatus: 在渲染 PDF 之前所需的窗口状态
  • encoding: 更改编码,默认为 UTF-8
  • download: 设置为 true 以强制下载,仅在使用 PdfView 时
  • filename: 使用强制下载时的文档文件名

示例

Configure::write('CakePdf', [
    'engine' => 'CakePdf.WkHtmlToPdf',
    'margin' => [
        'bottom' => 15,
        'left' => 50,
        'right' => 30,
        'top' => 45,
    ],
    'orientation' => 'landscape',
    'download' => true,
]);
use CakePdf\View\Pdfiew;

class InvoicesController extends AppController
{
    // In your Invoices controller you could set additional configs,
    // or override the global ones:
    public function view($id = null)
    {
        $invoice = $this->Invoice->get($id);
        $this->viewBuilder()->setOption(
            'pdfConfig',
            [
                'orientation' => 'portrait',
                'filename' => 'Invoice_' . $id,
            ]
        );
        $this->set('invoice', $invoice);
    }

    /**
     * Add Pdfiew::class to this $viewClasses property so that CakePHP automatically
     * switches the view class for URLs ending with `.pdf` or with appropriate `Accept` header.
     *
     * @see https://book.cakephp.com.cn/5/en/controllers.html#content-type-negotiation
     * @var array<string>
     */
    public function viewClasses(): array
    {
        return $this->viewClasses[] = Pdfiew::class;
    }
}

引擎和 crypto 配置选项也可以是包含相关类配置选项的数组。例如

Configure::write('CakePdf', [
    'engine' => [
        'className' => 'CakePdf.WkHtmlToPdf',
        // Options usable depend on the engine used.
        'options' => [
            'print-media-type' => false,
            'outline' => true,
            'dpi' => 96,
            'cover' => [
                'url' => 'cover.html',
                'enable-smart-shrinking' => true,
            ],
            'toc' => true,
        ],

        /**
         * For Mac OS X / Linux by default the `wkhtmltopdf` binary should
         * be available through environment path or you can specify location as:
         */
        // 'binary' => '/usr/local/bin/wkhtmltopdf',

        /**
         * On Windows the engine uses the path shown below as default.
         * You NEED to use the path like old fashioned MS-DOS Paths,
         * otherwise you will get error like:
         * "WKHTMLTOPDF didn't return any data"
         */
        // 'binary' => 'C:\\Progra~1\\wkhtmltopdf\\bin\\wkhtmltopdf.exe',
    ],
]);

使用方法

您可以使用 CakePdf 以两种方式,仔细阅读您实际需要哪种。很多人混用了这两种方法,但并没有得到预期的结果。

1: 使用 PdfView 在浏览器中渲染 PDF(包括强制下载)

您可以为控制器操作创建 PDF 模板和布局文件,并自动渲染它们。将模板放在 pdf 子目录中,例如 templates/Invoices/pdf/view.php,布局文件放在 templates/layout/pdf/default.php

例如,访问 URL http://localhost/invoices/view/1.pdf 将会得到生成的 PDF。

此外,您可以通过向路由文件中添加 Router::mapResources(['Invoices']); 来映射资源,并通过 http://localhost/invoices/1.pdf 访问相同的文档。

如果您不希望在 URL 中使用 pdf 扩展名,则可以在路由配置中省略注册它。然后,您可以将 Accept 请求头设置为 application/pdf 以使 CakePHP 自动切换到 PdfView(如上所示,需要设置 viewClasses() 方法),或者明确在控制器操作中切换视图类

$this->viewBuilder()->setClassName('CakePdf.Pdf');

除了在浏览器中直接渲染 PDF 外,您还可以使用 download 选项强制将其下载。此外,您还可以使用 filename 选项指定自定义文件名。

$this->viewBuilder()->setOption(
    'pdfConfig',
    [
        'download' => true, // This can be omitted if "filename" is specified.
        'filename' => 'Invoice_' . $id, // This can be omitted if you want a file name based on URL.
    ]
);

2: 创建用于电子邮件附件、文件存储等的 PDF

您可以使用 CakePdf 创建带有视图模板的原始 PDF 数据。视图文件路径看起来像 templates/pdf/newsletter.php。布局文件路径为 templates/layout/pdf/default.php 注意,两种使用类型的布局都在同一目录中,但视图模板使用不同的文件路径。可选地,您还可以将原始数据写入文件。

示例

$CakePdf = new \CakePdf\Pdf\CakePdf();
$CakePdf->template('newsletter', 'default');
$CakePdf->viewVars(['key' => 'value']);
// Get the PDF string returned
$pdf = $CakePdf->output();
// Or write it to file directly
$pdf = $CakePdf->write(APP . 'files' . DS . 'newsletter.pdf');

加密

您可以选择使用权限加密 PDF

要使用加密,您首先需要选择一个加密引擎。目前我们支持以下加密引擎

  • Pdftk

使用方法

在您的引导程序中添加以下内容。

Configure::write('CakePdf.crypto', 'CakePdf.Pdftk');

pdfConfig 中的选项

  • protect: 设置为 true 以启用加密
  • userPassword(可选):设置一个密码以打开 PDF 文件
  • ownerPassword(可选):设置密码以解锁已锁定权限
  • 上述之一必须存在,即 userPassword 或 ownerPassword
  • permissions(可选):定义权限

权限

默认情况下,我们拒绝所有权限。

要允许所有权限

将 'permission' 设置为 true

要允许特定权限

将 'permissions' 设置为包含以下可用权限组合的数组

  • print
  • degraded_print
  • modify,
  • assembly,
  • copy_contents,
  • screen_readers,
  • annotate,
  • fill_in

如何操作

确保 css、图片等在 PDF 中加载

对于 PDF 的视图模板中的静态资产使用绝对 URL。如果您使用 HtmlHelper::image()HtmlHelper::css(),请确保已将 fullBase 选项设置为 true

例如

echo $this->Html->image('logo.png', ['fullBase' => true]);
echo $this->Html->css('bootstrap.css', ['fullBase' => true]);

如果您无法正确获取资产 URL,您可以尝试使用文件系统路径代替资产。

<img src="<?= WWW_ROOT ?>img/logo.png" />

注意:由于 v0.12.16 版本,wkhtmltopdf 需要选项 enable-local-file-access 才能使用本地文件系统路径作为资产。您可以通过在引擎配置数组中将 'enable-local-file-access' => true 来启用它。

在所有页面上获取页眉和页脚

以下是一些基于 CSS 的解决方案,您可以在所有 PDF 页面上轻松获取页眉和页脚。