phpwkhtmltopdf

Special characters not working in PDF title but in PDF content when using wkhtmltopdf with php


I am using wkhtmltopdf to generate a pdf for my content within a Laravel app.

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>

The PDF looks fine (except CSS issues, different matter). On my local machine, the PDF that gets send to the browser tab, also shows the correct browser tab title, meaning special chars are displayed correctly in the browser tab (like umlauts). When I want to save the file, the suggested file name in the OS' save prompt is the same and also looks fine.

On production however, the title in the browser tab misses all special chars while when saving the file it suggests the correct file name again. So "können" for instance is displayed as "knnen" in the browser tab but the save prompt shows "können".

On both machines runs wkhtmltopdf 0.12.6 (with patched qt).

All I found in previous threads is adding utf encoding as meta and adding it as option, which I both did and locally it does work.

PS: buildPdfFileName is only used for the internal pdf name that gets saved and loaded locally, it is not the title/ filename suggestion.


Solution

  • When displaying a PDF, most browsers show the PDF title (when defined) in the tab title.

    To set the PDF title, you are using the title option, which is passed to wkhtmltopdf on the command line.

    First, you should check if $model->title is encoded in UTF-8 or not.

    Another possible explanation for the issue is that the PHP process has no LANG environment variable defined. In that case, the default locale is C, which supports only the ASCII encoding. All non-ASCII characters are considered invalid. A way to fix it is to add this before running wkhtmltopdf :

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

    Alternatively, you can define the PDF title via the <title> HTML tag. Just remove the title option and add the <title> tag to your HTML page. This is the most reliable solution because it avoids transmitting non-ASCII characters on the command line.