Sarim_Shahid's avatar

Issue with Embedding Custom Fonts in PDF using Spatie Browsershot in Laravel

Hello, I am working with Spatie Browsershot in a Laravel application to generate PDFs from HTML content. The issue I'm encountering is that custom fonts (specifically, NotoNastaliqUrdu-Regular) are not being embedded in the PDF when I either stream or download it. However, when viewed in a browser, the font is applied correctly.

I have tried multiple approaches, including using absolute file paths and setting the correct font-face in my Blade view, but the font is still not embedding in the generated PDF unless I use the --disable-web-security flag. While this resolves the issue, I am aware that disabling web security is not secure, and I would like to avoid it in a production environment.

Here is my controller code:

$html = view('admin.beopari.pdf.test')->render();

$pdf = Browsershot::html($html) ->setIncludePath('$PATH:/d/laragon/bin/nodejs/node-v18') ->setChromePath('C:\Program Files\Google\Chrome\Application\chrome.exe') ->waitFor('.urdu-font', 5000) // Wait for font to be applied ->waitUntilNetworkIdle() ->setOption('args', ['--no-sandbox', '--disable-gpu']) ->pdf();

return response($pdf, 200) ->header('Content-Type', 'application/pdf') ->header('Content-Disposition', 'inline; filename="example.pdf"'); And here is the Blade view code where I define the font:

@font-face { font-family: 'NotoNastaliqUrdu-Regular'; src: url("{{ public_path('admin_assets/assets/urdu/NotoNastaliqUrdu.ttf') }}") format("truetype"); }

.urdu-font { font-family: "NotoNastaliqUrdu-Regular"; font-optical-sizing: auto; font-weight: 500; font-style: normal; }

body { font-family: 'NotoNastaliqUrdu-Regular'; } What I've Tried So Far: Using absolute paths (public_path()) instead of asset(). Adding waitFor() and waitUntilNetworkIdle() to ensure that the font is loaded before generating the PDF. Using --disable-web-security, which works, but it is insecure for production. My Goal: I want to generate PDFs with custom fonts embedded securely, without the need to disable web security. Could anyone guide me on how to ensure that the font is embedded correctly in the PDF without compromising security?

Environment: Laravel Version: 11.x Browsershot Version: Latest Font: NotoNastaliqUrdu-Regular (truetype) Any help or suggestions would be greatly appreciated!

0 likes
1 reply
LaryAI's avatar
Level 58

To embed custom fonts in PDFs using Spatie Browsershot without disabling web security, you can try the following steps:

  1. Ensure Correct Font Path: Make sure the font path is accessible to the Browsershot process. Since Browsershot uses headless Chrome, it needs to access the font file directly. Use an absolute path to the font file in your CSS.

  2. Serve Fonts via HTTP: Instead of using public_path(), serve the font files via HTTP. This can be done by placing the font files in the public directory and using the asset() helper to generate the URL.

  3. Use a Local Web Server: Ensure that your local development server is running and accessible. Browsershot needs to fetch resources over HTTP, so the server must be running.

  4. Check Font MIME Type: Ensure that the server is serving the font files with the correct MIME type. You can add the following to your .htaccess file if you're using Apache:

    AddType application/font-woff2 .woff2
    AddType application/font-woff .woff
    AddType application/vnd.ms-fontobject .eot
    AddType font/ttf .ttf
    AddType font/otf .otf
    
  5. Update CSS: Modify your CSS to use the asset() helper for the font URL:

    <style>
    @font-face {
        font-family: 'NotoNastaliqUrdu-Regular';
        src: url("{{ asset('admin_assets/assets/urdu/NotoNastaliqUrdu.ttf') }}") format("truetype");
    }
    
    .urdu-font {
        font-family: "NotoNastaliqUrdu-Regular";
        font-optical-sizing: auto;
        font-weight: 500;
        font-style: normal;
    }
    
    body {
        font-family: 'NotoNastaliqUrdu-Regular';
    }
    </style>
    
  6. Ensure Network Access: Make sure that your local server is accessible from the environment where Browsershot is running. If you're running this in a Docker container or a VM, ensure that the network settings allow access to the local server.

  7. Debugging: Use the ->save() method to save the HTML output to a file and open it in a regular browser to ensure that the font is loading correctly. This can help you identify if the issue is with the font loading or with Browsershot.

By following these steps, you should be able to embed custom fonts in your PDFs securely without disabling web security. If the issue persists, consider checking the network requests in the headless Chrome instance to ensure that the font file is being requested and loaded correctly.

Please or to participate in this conversation.