在php中使用wkhtmltopdf时,特殊字符在PDF标题中不起作用,但在PDF内容中起作用

goucqfw6  于 2023-04-10  发布在  PHP
关注(0)|答案(3)|浏览(215)

bounty将在2天后过期。回答此问题可获得+100声望奖励。Alex正在寻找来自信誉良好的来源的答案

我正在使用wkhtmltopdf在Laravel应用程序中为我的内容生成PDF。
Controller.php

<?php

/**
 * @todo
 */
public function pdf($regionCode, $langCode, Model $model)
{
    $locale = LocalisationServiceProvider::getLocale($regionCode, $langCode);

    $pdfFileName = $this->buildPdfFileName($model->id, $locale);

    if (Storage::disk('root')->exists('public/storage/wkhtmltopdf/' . $pdfFileName)) {
        return response()->file(public_path('/storage/wkhtmltopdf/' . $pdfFileName));
    }

    $view = view('model.pdf', compact('model', 'locale'));
    $viewRendered = $view->render();

    $pdf = new Pdf([
        'binary' => env('WKHTMLTOPDF_BINARY_PATH'),
        'ignoreWarnings' => ('production' === env('APP_ENV')),
        'disable-smart-shrinking',
        'title' => $model->title . ' - Site.pdf',
        'encoding' => 'utf-8',
    ]);

    $pdf->addPage($viewRendered);

    if (!$pdf->saveAs(public_path('/storage/wkhtmltopdf/' . $pdfFileName))) {
        $error = $pdf->getError();
        // @todo log
        return response('An error occured', 500);
    }

    if (!$pdf->send($model->title . ' - Site.pdf', true)) {
        $error = $pdf->getError();
        return response('An error occured', 500);
    }
}

/**
 * @todo
 */
public function buildPdfFileName($id, $locale)
{
    return 'foobar_' . $id . '_' . $locale . '.pdf';
}

pdf.blade.php

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <meta charset="UTF-8">
    </head>
    <body>
        <div id="canvas" class="position-relative">

            @hasSection('header')
                <header id="header">
                    @yield('header')
                </header>
            @endif

            @hasSection('main')
                <main role="main" id="main-content">
                    @yield('main')
                </main>
            @endif

        </div>
    </body>
</html>

PDF看起来很好(除了CSS问题,不同的问题)。在我的本地机器上,发送到浏览器选项卡的PDF也显示了正确的浏览器选项卡标题,这意味着特殊字符在浏览器选项卡中正确显示(如变音)。当我想保存文件时,操作系统保存提示中的建议文件名是相同的,看起来也很好。
但是在生产环境中,浏览器标签页中的标题会丢失所有特殊字符,而在保存文件时,它会再次建议正确的文件名。例如,“können”在浏览器标签页中显示为“knnen”,但保存提示符显示为“können”。
在两台机器上运行wkhtmltopdf 0.12.6 (with patched qt)
我在以前的线程中发现的所有内容都是将UTF编码添加为 meta并将其添加为option,我都这样做了,并且在本地它确实工作。
PS:buildPdfFileName只用于在本地保存和加载的内部pdf名称,它不是标题/文件名建议。

gj3fmq9x

gj3fmq9x1#

问题可能是运行代码的生产环境的编码问题。
特别是,也因为你说你的操作系统在从生产环境下载文件时正确处理了文件名,所以在生产环境中,你应该检查渲染网页/pdf的脚本是否设置了正确的编码,以便将输出发送到浏览器(在你的情况下是pdf)。
通常,浏览器使用由网页递送的编码。
你可以尝试这些尝试:

  • 除了在呈现的HTML中设置Content-Type之外,在将任何输出发送到浏览器之前,也尝试在PHP脚本中设置它。
  • 尝试对标题进行编码:'title' => urlencode($model->title . ' - Site.pdf'),
  • 将其设置为wkhtmltopdf选项:
$pdf = new Pdf([
    'binary' => env('WKHTMLTOPDF_BINARY_PATH'),
    'ignoreWarnings' => ('production' === env('APP_ENV')),
    'disable-smart-shrinking',
    'title' => $model->title . ' - Site.pdf',
    // 'encoding' => 'utf-8',
    'options' => array(
        'encoding' => 'utf-8'
    ),
]);
v8wbuo2f

v8wbuo2f2#

显示PDF时,大多数浏览器会在选项卡标题中显示PDF标题(定义时)。
要设置PDF标题,可以使用title选项,该选项在命令行中传递给wkhtmltopdf。
首先,您应该检查$model->title是否使用UTF-8编码。
另一个可能的解释是PHP进程没有定义LANG环境变量。在这种情况下,默认的locale是C,它只支持ASCII编码。所有非ASCII字符都被认为是无效的。解决这个问题的一个方法是在运行wkhtmltopdf之前添加这个:

putenv('LANG=de_DE.UTF-8');

或者,您可以通过<title> HTML标签定义PDF标题。只需删除title选项并将<title>标签添加到HTML页面。这是最可靠的解决方案,因为它避免了在命令行上传输非ASCII字符。

6g8kf2rb

6g8kf2rb3#

我不认为这与

  • PDF或
  • 用户语言或
  • 服务手段

在URL中不使用非拉丁UTF字符是一种传统做法,因为它们需要转换为不同操作系统、本地化、应用程序等的“安全”范围,而拉丁美洲在历史上是通用资源位置友好的。

局部发现时,仍有2种不同结局

每个浏览器负责选择标签标题,请注意,中间的标签与所有其他标签相同,但浏览器询问我是否希望将其从德语更改为英语。

所以对于你的答案,操作系统在生产过程中处理文件名,这里一切都很好,但浏览器决定为他们自己的基础上加载的html标题或第二次任何其他覆盖像用户选择标签名称或提示从重新加载. PDF,其中PDF字符串将被正确地注入为PDF BOM-UTF-16 BE由wkHTML如说/Title (þÿ T i t e l k ö n n e n f u n k t i o n i e r e n),然后它的浏览器转换成一个人类可读的字符串英语,德语UTF-8 URL编码或任何外观。

相关问题