Skip to content
Advertisement

fjsPDF in Node.js environment loads a black square as opposed to a png image

I am attempting to generate a pdf file in a node.js environment. I am running node v 14.17.6. The issue I am seeing is that when I attempt to load a png image from the working directory, the image in the pdf is instead just a black square taking up the same space. I’ve attempted to save the image with transparency removed as I’ve seen some issues with this.

Note: This is all done in a node.js environment, not in the browser. I’ve spent over an hour looking for duplicates, but most duplicates seem to be centered on manipulation with the canvas or img element in the browser environment and not all on the server side.

The below code is a massively scaled down reproduction of the issue (all you need is a package.json file with jspdf @ 2.5.1 and an image in the same directory, in this case blue.png)

import fs from 'fs';
import { jsPDF } from 'jspdf';

const file = fs.readFileSync('blue.png');
const fileUri = `data:image/png;base64,${file.toString('base64')}`;

const pdf = new jsPDF('p', 'mm', [400, 500]);
pdf.addImage(fileUri, 'png', 100, 100, 200, 300);

fs.writeFileSync('test.pdf', pdf.output());

package.json is here:

{
  "name": "stack",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo "Error: no test specified" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "type": "module",
  "dependencies": {
    "jspdf": "^2.5.1"
  }
}

Updated:

import fs from 'fs';
import { jsPDF } from 'jspdf';
import Base64 from 'base-64';
import PNGJS from 'png-js';

const file = fs.readFileSync('blue.png');
console.log(file);
const fileUri = `data:image/png;base64,${file.toString('base64')}`;

global.btoa = Base64.encode; 
global.html2pdf = {};
global.window = {document: {createElementNS: () => {return {}} }};
global.navigator = {};
global.PNG = PNGJS;

const pdf = new jsPDF();
pdf.addImage(fileUri, 'PNG', 40, 20, 0, 0);
fs.writeFileSync('test.pdf', pdf.output());

delete global.btoa;
delete global.PNG;
delete global.window;
delete global.navigator;
delete global.html2pdf;

DataUri: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAOEAAADhCAIAAACx0UUtAAAABGdBTUEAALGPC/xhBQAACklpQ0NQc1JHQiBJRUM2MTk2Ni0yLjEAAEiJnVN3WJP3Fj7f92UPVkLY8LGXbIEAIiOsCMgQWaIQkgBhhBASQMWFiApWFBURnEhVxILVCkidiOKgKLhnQYqIWotVXDjuH9yntX167+3t+9f7vOec5/zOec8PgBESJpHmomoAOVKFPDrYH49PSMTJvYACFUjgBCAQ5svCZwXFAADwA3l4fnSwP/wBr28AAgBw1S4kEsfh/4O6UCZXACCRAOAiEucLAZBSAMguVMgUAMgYALBTs2QKAJQAAGx5fEIiAKoNAOz0ST4FANipk9wXANiiHKkIAI0BAJkoRyQCQLsAYFWBUiwCwMIAoKxAIi4EwK4BgFm2MkcCgL0FAHaOWJAPQGAAgJlCLMwAIDgCAEMeE80DIEwDoDDSv+CpX3CFuEgBAMDLlc2XS9IzFLiV0Bp38vDg4iHiwmyxQmEXKRBmCeQinJebIxNI5wNMzgwAABr50cH+OD+Q5+bk4eZm52zv9MWi/mvwbyI+IfHf/ryMAgQAEE7P79pf5eXWA3DHAbB1v2upWwDaVgBo3/ldM9sJoFoK0Hr5i3k4/EAenqFQyDwdHAoLC+0lYqG9MOOLPv8z4W/gi372/EAe/tt68ABxmkCZrcCjg/1xYW52rlKO58sEQjFu9+cj/seFf/2OKdHiNLFcLBWK8ViJuFAiTcd5uVKRRCHJleIS6X8y8R+W/QmTdw0ArIZPwE62B7XLbMB+7gECiw5Y0nYAQH7zLYwaC5EAEGc0Mnn3AACTv/mPQCsBAM2XpOMAALzoGFyolBdMxggAAESggSqwQQcMwRSswA6cwR28wBcCYQZEQAwkwDwQQgbkgBwKoRiWQRlUwDrYBLWwAxqgEZrhELTBMTgN5+ASXIHrcBcGYBiewhi8hgkEQcgIE2EhOogRYo7YIs4IF5mOBCJhSDSSgKQg6YgUUSLFyHKkAqlCapFdSCPyLXIUOY1cQPqQ28ggMor8irxHMZSBslED1AJ1QLmoHxqKxqBz0XQ0D12AlqJr0Rq0Hj2AtqKn0UvodXQAfYqOY4DRMQ5mjNlhXIyHRWCJWBomxxZj5Vg1Vo81Yx1YN3YVG8CeYe8IJAKLgBPsCF6EEMJsgpCQR1hMWEOoJewjtBK6CFcJg4Qxwicik6hPtCV6EvnEeGI6sZBYRqwm7iEeIZ4lXicOE1+TSCQOyZLkTgohJZAySQtJa0jbSC2kU6Q+0hBpnEwm65Btyd7kCLKArCCXkbeQD5BPkvvJw+S3FDrFiOJMCaIkUqSUEko1ZT/lBKWfMkKZoKpRzame1AiqiDqfWkltoHZQL1OHqRM0dZolzZsWQ8ukLaPV0JppZ2n3aC/pdLoJ3YMeRZfQl9Jr6Afp5+mD9HcMDYYNg8dIYigZaxl7GacYtxkvmUymBdOXmchUMNcyG5lnmA+Yb1VYKvYqfBWRyhKVOpVWlX6V56pUVXNVP9V5qgtUq1UPq15WfaZGVbNQ46kJ1Bar1akdVbupNq7OUndSj1DPUV+jvl/9gvpjDbKGhUaghkijVGO3xhmNIRbGMmXxWELWclYD6yxrmE1iW7L57Ex2Bfsbdi97TFNDc6pmrGaRZp3mcc0BDsax4PA52ZxKziHODc57LQMtPy2x1mqtZq1+rTfaetq+2mLtcu0W7eva73VwnUCdLJ31Om0693UJuja6UbqFutt1z+o+02PreekJ9cr1Dund0Uf1bfSj9Rfq79bv0R83MDQINpAZbDE4Y/DMkGPoa5hpuNHwhOGoEctoupHEaKPRSaMnuCbuh2fjNXgXPmasbxxirDTeZdxrPGFiaTLbpMSkxeS+Kc2Ua5pmutG003TMzMgs3KzYrMnsjjnVnGueYb7ZvNv8jYWlRZzFSos2i8eW2pZ8ywWWTZb3rJhWPlZ5VvVW16xJ1lzrLOtt1ldsUBtXmwybOpvLtqitm63Edptt3xTiFI8p0in1U27aMez87ArsmuwG7Tn2YfYl9m32zx3MHBId1jt0O3xydHXMdmxwvOuk4TTDqcSpw+lXZxtnoXOd8zUXpkuQyxKXdpcXU22niqdun3rLleUa7rrStdP1o5u7m9yt2W3U3cw9xX2r+00umxvJXcM970H08PdY4nHM452nm6fC85DnL152Xlle+70eT7OcJp7WMG3I28Rb4L3Le2A6Pj1l+s7pAz7GPgKfep+Hvqa+It89viN+1n6Zfgf8nvs7+sv9j/i/4XnyFvFOBWABwQHlAb2BGoGzA2sDHwSZBKUHNQWNBbsGLww+FUIMCQ1ZH3KTb8AX8hv5YzPcZyya0RXKCJ0VWhv6MMwmTB7WEY6GzwjfEH5vpvlM6cy2CIjgR2yIuB9pGZkX+X0UKSoyqi7qUbRTdHF09yzWrORZ+2e9jvGPqYy5O9tqtnJ2Z6xqbFJsY+ybuIC4qriBeIf4RfGXEnQTJAntieTE2MQ9ieNzAudsmjOc5JpUlnRjruXcorkX5unOy553PFk1WZB8OIWYEpeyP+WDIEJQLxhP5aduTR0T8oSbhU9FvqKNolGxt7hKPJLmnVaV9jjdO31D+miGT0Z1xjMJT1IreZEZkrkj801WRNberM/ZcdktOZSclJyjUg1plrQr1zC3KLdPZisrkw3keeZtyhuTh8r35CP5c/PbFWyFTNGjtFKuUA4WTC+oK3hbGFt4uEi9SFrUM99m/ur5IwuCFny9kLBQuLCz2Lh4WfHgIr9FuxYji1MXdy4xXVK6ZHhp8NJ9y2jLspb9UOJYUlXyannc8o5Sg9KlpUMrglc0lamUycturvRauWMVYZVkVe9ql9VbVn8qF5VfrHCsqK74sEa45uJXTl/VfPV5bdra3kq3yu3rSOuk626s91m/r0q9akHV0IbwDa0b8Y3lG19tSt50oXpq9Y7NtM3KzQM1YTXtW8y2rNvyoTaj9nqdf13LVv2tq7e+2Sba1r/dd3vzDoMdFTve75TsvLUreFdrvUV99W7S7oLdjxpiG7q/5n7duEd3T8Wej3ulewf2Re/ranRvbNyvv7+yCW1SNo0eSDpw5ZuAb9qb7Zp3tXBaKg7CQeXBJ9+mfHvjUOihzsPcw83fmX+39QjrSHkr0jq/dawto22gPaG97+iMo50dXh1Hvrf/fu8x42N1xzWPV56gnSg98fnkgpPjp2Snnp1OPz3Umdx590z8mWtdUV29Z0PPnj8XdO5Mt1/3yfPe549d8Lxw9CL3Ytslt0utPa49R35w/eFIr1tv62X3y+1XPK509E3rO9Hv03/6asDVc9f41y5dn3m978bsG7duJt0cuCW69fh29u0XdwruTNxdeo94r/y+2v3qB/oP6n+0/rFlwG3g+GDAYM/DWQ/vDgmHnv6U/9OH4dJHzEfVI0YjjY+dHx8bDRq98mTOk+GnsqcTz8p+Vv9563Or59/94vtLz1j82PAL+YvPv655qfNy76uprzrHI8cfvM55PfGm/K3O233vuO+638e9H5ko/ED+UPPR+mPHp9BP9z7nfP78L/eE8/stRzjPAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAAJcEhZcwAACxMAAAsTAQCanBgAAAMQSURBVHic7d1NTttgFEDRDydkkG2wBnbBClkII9bCIvgTP3booBITIGqlFt+q50xj63uDq2dFiuKTw+Ht4WHc3o77+/H0NF5exhjj7m78tCzj+Xm8e3wcn3p9HYfD5x99tCy/emXEZvMdp2y333TQ+3G73fcdN8bY73/7lmUZZ2dje3U1Li7+wkTwJ1xejmntGeCY3U6j5GmUuumrr0EQYY9Sp1HqNEqdRqnTKHUapU6j1GmUOo1Sp1HqNErd9M/94pj/zTTPa48AR3nWU6dR6jRKnUap0yh1GqVOo9RplDqNUqdR6jRKnUap0yh1GqVOo9RplDqNUqdR6jRKnUap0yh1GqVOo9RplDqNUqdR6jRKnUap0yh1GqVOo9RplDr/40ydPUqdRqnTKHUapU6j1GmUOo1Sp1HqNEqdRqnTKHUapU6j1GmUOo1Sp1HqNEqdRqnTKHUapU6j1GmUOo1Sp1HqNEqdRqnTKHUapU6j1GmUOo1Sp1HqNEqdRqnTKHUapU6j1GmUOo1SN202a48AR9mj1GmUOo1Sp1HqNEqdRqnTKHUapU6j1GmUOo1Sp1HqNEqdRqnTKHUapU6j1GmUOo1Sp1HqNEqdRqnTKHUapU6j1GmUOo1Sp1HqNEqdRqnTKHUapU6j1GmUOo1Sp1HqNEqdRqnTKHXTpFLaptPTtUeAo2xR6jRKnUap0yh1GqVOo9RplDqNUqdR6jRKnUap0yh1GqVOo9RplDqNUqdR6jRKnUap0yh1GqVOo9RplDqNUqdR6jRKnUap0yh1GqVOo9RplDqNUqdR6jRKnUap0yh1036/9ghwlD1KnUap0yh1GqVOo9RplDqNUqdR6jRKnUap0yh1GqVOo9RplDqNUqdR6jRKnUap0yh1GqVOo9RplDqNUqdR6jRKnUap0yh1GqVOo9RplDqNUqdR6jRKnUap0yh1GqXOOxuos0ep0yh1GqVOo9RplDqNUqdR6jRKnUap0yh1GqVOo9RplDqNUqdR6jRK3bQsa48AX5vncXJz83Z9PXa7tWeBD+Z5nJ+PH111NGmKv70bAAAAAElFTkSuQmCC

Update: The answer was with the writeFileSync function. I used the default encoding (utf-8) by not specifying this parameter. This does not work. Specifying either ‘binary’ or ‘ascii’ as in the answer below made this work.

fs.writeFileSync('test.pdf', pdf.output(), 'ascii');

Advertisement

Answer

I’ve referred to the code provided in the examples of the jspdf library and its working perfectly fine for me. See below image for code output.

enter image description here

Adding below the code example here as well for more visibility.

...imports

var Octocat = fs.readFileSync("../images/Octocat.png", { encoding: "latin1" });

var doc = new jsPDF();

doc.setFontSize(40);
doc.text("Octocat loves jsPDF", 40, 30, 4);
doc.addImage(Octocat, "test", 10, 40, 180, 180, undefined, "SLOW");

fs.writeFileSync("./Octocat.pdf", doc.output(), "ascii");

Please comment if I misunderstood your question.

User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement