9

I have the following code I am using to test drive PDFmake. I am having an issue with the location of the font files. I see documentation that seem to indicate that after pulling in the vfs_fonts file that I should be able to see them. However this is not the case for me.

function createPdf(assessmentId: string): string {
  const pdfMake = require('pdfmake/build/pdfmake.js');
  const pdfFonts = require('pdfmake/build/vfs_fonts.js');
  pdfMake.vfs = pdfFonts.pdfMake.vfs;

  //required font setup, requires that you link to the fonts shipped with npm

  const fontDescriptors = {
    Roboto: {
      normal: 'Roboto-Regular.ttf',
      bold: 'Roboto-Medium.ttf',
      italics: 'Roboto-Italic.ttf',
      bolditalics: 'Roboto-Italic.ttf',
    }
  };
  const termpaper = new PdfLayout();
  const docDefinition = termpaper.layout
  const printer = new Printer(fontDescriptors);

  //get a reference to the PdfKit instance, which is a streaming interface

  const pdfDoc = printer.createPdfKitDocument(docDefinition);

  return "pdflocation";
}

When this code executes I get this error.

Error:

ENOENT: no such file or directory, open 'Roboto-Medium.ttf' at Error (native) at Object.fs.openSync (fs.js:642:18) at Object.fs.readFileSync (fs.js:510:33) at Object.fontkit.openSync (/user_code/node_modules/pdfmake/node_modules/fontkit/index.js:43:19) at Function.PDFFont.open (/user_code/node_modules/pdfmake/node_modules/pdfkit/js/font.js:14:24) at PDFDocument.font (/user_code/node_modules/pdfmake/node_modules/pdfkit/js/mixins/fonts.js:39:28) at FontProvider.provideFont (/user_code/node_modules/pdfmake/src/fontProvider.js:49:58) at /user_code/node_modules/pdfmake/src/textTools.js:258:27 at Array.forEach (native) at measure (/user_code/node_modules/pdfmake/src/textTools.js:240:13)

What do I need to do to properly find these font files?

Christophvh
  • 12,586
  • 7
  • 48
  • 70
user1247395
  • 409
  • 1
  • 9
  • 20

10 Answers10

9

I struggled with this too. The solution I found was to actually include the font files in my project. The files listed are in the 'fonts' folder at the root of my project, and my code references them by uri:

const fonts = {
    Roboto: {
        normal: 'fonts/Roboto-Regular.ttf',
        bold: 'fonts/Roboto-Medium.ttf',
        italics: 'fonts/Roboto-Italic.ttf',
        bolditalics: 'fonts/Roboto-MediumItalic.ttf'
    }
};

I downloaded the font files from here.

Hope this helps.

rozza2058
  • 560
  • 1
  • 3
  • 11
6

You can also use like this, In my case my fonts, controllers, helper directory inside workspace directory.

const path = require('path'); // path is give you a working directory path.resolve() and you can give your font file path.

const fontDescriptors = {
  Roboto: {
    normal: path.resolve('./fonts/Roboto-Regular.ttf'),
    bold: path.resolve('./fonts/Roboto-Medium.ttf'),
    italics: path.resolve('./fonts/Roboto-Italic.ttf'),
    bolditalics: path.resolve('./fonts/Roboto-MediumItalic.ttf')
  }
}
Gautam Ajani
  • 71
  • 1
  • 3
2

Had similar problem once, you needed to give exact location of the fonts.

It also has marked notification before fonts.

//required font setup, requires that you link to the fonts shipped with npm


Try full directory paths on these:

    normal: '/Exampledir/pdfmake/Roboto-Regular.ttf',
    bold: 'Roboto-Medium.ttf',
    italics: 'Roboto-Italic.ttf',
    bolditalics: 'Roboto-Italic.ttf',

Or there is / missing from
const pdfFonts = require("pdfmake/

Eg.
const pdfFonts = require("/pdfmake/

It was that simple as error indicates it can't find fonts from that location, overcheck the location with simple cd ./ then cd /pdfmake/ etc and ls. Compare config file and should get it working.

Cemtey
  • 155
  • 7
2

You can very well use custom fonts by simple 3 steps :

To use custom fonts, 3 steps are required:

  • create vfs_fonts.js containing your fonts
  • define font family
  • change font family in doc-definition-object

1. Create vfs_fonts.js containing your fonts

Copy your fonts to myProject/fonts/ directory

Run grunt dump_dir (you can update Gruntfile.js if you'd like to change base directory or add an alternative config for dump_dir task)

Use your new build/vfs_fonts.js on your web page

BTW - the above action dumps all files from myProject/fonts/ (not only fonts), which means you could put images there, run grunt dump_dir and reference them by name in doc-definition-object

2. Define font family

Before calling pdfMake.createPdf(docDefinition) set pdfMake.fonts to the following object:

{
   yourFontName: {
     normal: 'fontFile.ttf',
     bold: 'fontFile2.ttf',
     italics: 'fontFile3.ttf',
     bolditalics: 'fontFile4.ttf'
   },
   anotherFontName: {
     (...)
   }
}

Keys are font-family names you can later use in doc-definition

Each font-family defines 4 properties: normal, bold, italics and bold-italics referring to appropriate files (by default these are file paths relative to myProject/fonts/)

By default pdfMake uses the following structure:

{
        Roboto: {
                normal: 'Roboto-Regular.ttf',
                bold: 'Roboto-Medium.ttf',
                italics: 'Roboto-Italic.ttf',
                bolditalics: 'Roboto-Italic.ttf'
        }
};

3. Change font family in doc-definition-object

Currently pdfmake uses 'Roboto' as default family name, so in order to use your font, you should change it. The easiest way is to do it globally in defaultStyle

var docDefinition = {
  content: (...),
  defaultStyle: {
    font: 'yourFontName'
  }
}

So, ideally, I would suggest you to download and put all the font files you want in a folder, say myProject/fonts/ and then try referencing the same in your code. The correct snippet of your code would look similar to this :

const fontDescriptors = {
    Roboto: {
      normal: 'myProject/fonts/Roboto-Regular.ttf',
      bold: 'myProject/fonts/Roboto-Medium.ttf',
      italics: 'myProject/fonts/Roboto-Italic.ttf',
      bolditalics: 'myProject/fonts/Roboto-Italic.ttf',
    }
};

Hope this would solve your issue. Feel free to ask doubts, if any.

Zac
  • 1,305
  • 3
  • 17
  • 28
1

This error mostly comes when you work with webpack. We are using webpack and managed to fix this by shimming this to window with the webpack imports-loader like this:

var fonts = require('imports?this=>window!pdfmake/build/vfs_fonts.js');

Fix:

function createPdf(assessmentId: string): string {

  const pdfMake = require('pdfmake/build/pdfmake.js');

  const pdfFonts = require('pdfmake/build/vfs_fonts.js');// this line will give an error if you are working with webpack . 

var fonts = require('imports?this=>window!pdfmake/build/vfs_fonts.js'); //use this line to fix it

  pdfMake.vfs = pdfFonts.pdfMake.vfs;

  //required font setup, requires that you link to the fonts shipped with npm

  const fontDescriptors = {
    Roboto: {
      normal: 'Roboto-Regular.ttf',
      bold: 'Roboto-Medium.ttf',
      italics: 'Roboto-Italic.ttf',
      bolditalics: 'Roboto-Italic.ttf',
    }
  };
  const termpaper = new PdfLayout();
  const docDefinition = termpaper.layout
  const printer = new Printer(fontDescriptors);

  //get a reference to the PdfKit instance, which is a streaming interface

  const pdfDoc = printer.createPdfKitDocument(docDefinition);

  return "pdflocation";
}

Hope this can be helpful for others!

0

I'm using React and datatables.net. This is what worked for me:

import React from 'react';
import $ from 'jquery';

import 'datatables.net-bs';
import 'datatables.net-buttons-bs';
import 'datatables.net-responsive-bs';
import 'datatables.net-buttons/js/buttons.colVis.js';
import 'datatables.net-buttons/js/buttons.flash.js';
import 'jszip';
import pdfMake from 'pdfmake/build/pdfmake';
import pdfFonts from 'pdfmake/build/vfs_fonts';
import 'datatables.net-buttons/js/buttons.html5.js';
import 'datatables.net-buttons/js/buttons.print.js';

import 'bootstrap/dist/css/bootstrap.min.css';
import 'datatables.net-bs/css/dataTables.bootstrap.css';

$.DataTable = require('datatables.net');
pdfMake.vfs = pdfFonts.pdfMake.vfs; // This line solved the Roboto errors

require("datatables.net-buttons/js/buttons.colVis.js"); // Column visibility
require("datatables.net-buttons/js/buttons.html5.js"); // HTML 5 file export
require("datatables.net-buttons/js/buttons.flash.js"); // Flash file export
require("datatables.net-buttons/js/buttons.print.js"); // Print view button
jade290
  • 413
  • 6
  • 5
0

I recently ran into this issue. I have tried to follow the steps on their docs but I found the same error as you did. My fonts were successfully added to a subdirectory in my node_modules. My mistake was when I ran the command gulp buildFonts, it didn't add the prepared fonts in the vfs_fonts.js file.

It turns out that we have to put the fonts exactly in examples/fonts subdirectory. Or alternatively you can reconfigure the gulpfile.js so the default subdirectory is changed to the one you wanted to put the fonts to.

Hope this helps.

lorem_impus
  • 320
  • 3
  • 9
0

For those who use React (TypeScript) with Vite and end up here, I managed to find a very easy solution for this.

PDFMake Docs says you should import the library as follows:

import * as pdfMake from 'pdfmake/build/pdfmake';
import * as pdfFonts from 'pdfmake/build/vfs_fonts';

(pdfMake as any).vfs = pdfFonts.pdfMake.vfs;

This works fine in development but when build the app, "pdfFonts.pdfMake" becomes undefined. So it doesn't work.

So I analyzed the production build and saw that the build contains a part like this which inludes the fonts object

globalThis.pdfMake = globalThis.pdfMake || {};
globalThis.pdfMake.vfs = {
    "Roboto-Italic.ttf": "AAEAAAARAQAABAAQR0RFRqWLoiAAAdT4AA=...",
    "Roboto-Medium.ttf": "AAEAAAARAQAABAAQR0RFRqWLoiAAAb9IAA...",
    "Roboto-MediumItalic.ttf": "AAEAAAARAQAABAAQR0RFRqWLoiAAAd==....",
    "Roboto-Regular.ttf": "AAEAAAARAQAABAAQR0RFRqWLoiAAAb8IAAACWA=....",
};

Since the fonts are already there, we can use them to resolve the issue:

import * as pdfMake from 'pdfmake/build/pdfmake';
import * as pdfFonts from 'pdfmake/build/vfs_fonts';

(pdfMake as any).vfs =
  pdfFonts && pdfFonts.pdfMake ? pdfFonts.pdfMake.vfs : globalThis.pdfMake.vfs;

Now this will work on both development phase and production build without any problems.

Alper Güven
  • 329
  • 4
  • 15
-1
function createPdf(assessmentId: string): string {
  const pdfMake = require("pdfmake/build/pdfmake.js");
  const pdfFonts = require("pdfmake/build/vfs_fonts.js");
  pdfMake.vfs = pdfFonts.pdfMake.vfs;
  const projectId = "crds-wayfinder-int";
  const philstorage = new gcs({
    projectId: projectId
  });

  // required font setup, requires that you link to the fonts shipped with npm

  const termpaper = new PdfLayout();
  const docDefinition = termpaper.layout;

  // get a reference to the PdfKit instance, which is a streaming interface
  const pdfDoc = pdfMake.createPdf(docDefinition);
  pdfDoc.getBuffer((buffer: any) => {
    console.log('buffer: ', buffer);
  });

  console.log('pdfDoc: ', pdfDoc);

  return "pdflocation";
}
user1247395
  • 409
  • 1
  • 9
  • 20
-1

for electron (@vue-cli with electron-builder) this finally worked for me:

yarn add pdfmake

then in js/coffeescript code:

import pdfMake from 'pdfmake/build/pdfmake.min.js'
import pdfFonts from 'pdfmake/build/vfs_fonts.js'

# this did the trick:
pdfMake.vfs = pdfFonts.pdfMake.vfs

hope that helps!

weHe
  • 434
  • 4
  • 5