Home Lập trình webLaravel FrameworkCác lỗi thường gặp Sửa lỗi font chữ khi sử dụng dompdf + php laravel

Sửa lỗi font chữ khi sử dụng dompdf + php laravel

by Anh Trần
dompdf font issue

Vừa rồi mình có làm một task xuất PDF từ template HTML sử dụng dompdf. Rất đen, mình đã dính lỗi font tiếng Nhật trong file PDF xuất ra. Cũng lên google search “dompdf japanese issue“, “dompdf fonts issue“, “dompdf chinese issue” bla bla. Người gặp lỗi này có vẻ cũng nhiều, tuy nhiên chưa thấy có một hướng dẫn đầy đủ nào. Bài viết này sẽ giúp các bạn fix lỗi trên và hiểu nguyên nhân của nó.

Mô tả dompdf error khi export tiếng Nhật

Mình sử dụng laravel framework 6.0; package laravel dompdf từ:

https://github.com/barryvdh/laravel-dompdf

Chú ý: Đây là lỗi chung của dompdf. Nên nếu bạn sử dụng framework khác, việc theo hướng dẫn dưới đây chắc hẳn vẫn sẽ có ích.

Đầu tiên, đây sẽ là format mình export thành công:

laravel dompdf font
đây là file export thành công.

Đây là điều xảy ra khi mình sử dụng font “DejaVu sans”:

 body {
    font-family: DejaVu Sans, sans-serif;
 }

dompdf font error

Các bạn có thể thấy, các kí tự tiếng Nhật đã biến mất. Điều này xảy ra do font DejaVu Sans không hỗ trợ các kí tự tiếng Nhật. Và mặc định, dompdf không có các font support cho tiếng Nhật, Trung, Hàn,…

Do đó, việc bạn cần làm là import cho thư viện một font hỗ trợ tiếng Nhật. Tuy nhiên, việc import thực sự không đơn giản. Bạn cần phải sử dụng file load_font.php để thực hiện import. Các phiên bản trước đây có đóng gói sẵn file này. Tuy nhiên, với dompdf phiên bản mới, bạn cần tải về từ đường dẫn sau:

https://github.com/dompdf/utils/blob/master/load_font.php

Hướng dẫn import font tiếng Nhật vào dompdf

Có nhiều font chữ cho tiếng Nhật, bạn có thể dễ dàng tìm kiếm, tải, cài đặt qua bác Google nhé :D. Ở đây mình sử dụng font aozoraminchomedium.

Đầu tiên, bạn cần tải font về, giải nén nó vào một vị trí trên ổ cứng. Sau đó, run file load_font.php bằng command line:

php load_font.php aozoraminchomedium $path_to_font_directory/aozoraminchomedium.ttf

Trong đó, $path_to_font_directory là thư mục mà bạn đã lưu tệp aozoraminchomedium.ttf. Giá trị phụ thuộc vào nơi bạn lưu nó. Màn hình command hiển thị như sau là thành công:

Unable to find bold face file.
Unable to find italic face file.
Unable to find bold_italic face file.
Copying $path_to_font_directory/ aozoraminchomedium.ttf to $laravel_install_directory /vendor/dompdf/dompdf/lib/fonts/aozoraminchomedium.ttf...
Generating Adobe Font Metrics for $laravel_install_directory /vendor/dompdf/dompdf/lib/fonts/aozoraminchomedium ...

Nếu phông chữ được cài đặt thành công, aozoraminchomedium.ttf sẽ tồn tại trong / vendor/ dompdf / dompdf / lib / scripts / và aozoraminchomedium .ufm cũng sẽ được tạo . Bạn cũng có thể thấy rằng thông tin của font aozoraminchomedium đã được thêm vào /storage/fonts/dompdf_font_family_cache.php:

'aozoraminchomedium' => array(
    'normal' => $fontDir . '/AozoraMinchoMedium',
    'bold' => $fontDir . '/AozoraMinchoMedium',
    'italic' => $fontDir . '/AozoraMinchoMedium',
    'bold_italic' => $fontDir . '/AozoraMinchoMedium',
),

Như vậy, việc set up font chữ tiếng Nhật đã hoàn tất

Tạo file PDF với font chữ tiếng Nhật

Bây giờ, chúng ta sẽ thử tạo một file pdf với font chữ tiếng Nhật để xem kết quả thu được như thế nào nhé!

Tạo controller với function printPdf:

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\User;
use PDF;

class PdfController extends Controller
{
    public function printPdf()
    {
        $users = User::all();

        $pdf = PDF::loadView('user.index', compact('users'));

        return $pdf->download('user_list.pdf');
    }
}

Tạo template (chú ý phần meta charset=utf-8):

<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Create PDF</title>
<style>
body {
font-family: aozoraminchomedium;
}
</style>
</head>
<body>
<div class="container">
    <div class="row">
        <div class="col-md-12">
        <h1>user list</h1>
        <table>
        <thead>
            <tr>
                <th>ユーザID</th>
                <th>ユーザ名</th>
                <th>E-mail</th>
            </tr>
        </thead>
        <tbody>
            @foreach ($users as $user)
            <tr>
                <td>{{ $user->id }}</td>
                <td>{{ $user->name }}</td>
                <td>{{ $user->email }}</td>
            </tr>
            @endforeach
        </tbody>
        </table>
        </div>
    </div> 
</div>
</body>
</html>

Route:

Route::resource('/pdf','PdfController');

Hoàn thành 😀

You may also like

Leave a Comment