node-html-pdf icon indicating copy to clipboard operation
node-html-pdf copied to clipboard

The image is not show after convert to pdf

Open alatebloomer opened this issue 7 years ago • 15 comments

Below is my html code

<div>
  <img src="./cscps/images/aaa.bmp">
  <img src="./cscps/images/bbb.bmp">
  <img src="./cscps/images/ccc.bmp">
  <img src="./cscps/images/ddd.bmp">
</div>

and I set "base" option like below

var options = { 
format: 'Letter',
base: 'file://./cscps/images/' 

};

But still can not see any image in pdf file.

Anyone can help? I am using MAC system Thanks.

alatebloomer avatar Feb 16 '17 19:02 alatebloomer

Might help https://github.com/marcbachmann/node-html-pdf/issues/44

waila7 avatar Feb 24 '17 10:02 waila7

Calculate the full path on your server and put that as base. The src path should be aaa.bmp if your vase goes all the way down to images. Good luck.

derouck avatar Mar 08 '17 16:03 derouck

file://./cscps/images/ is a relative path from the phantomjs executable. This is wrong in most cases.

Please use base: 'file://' + __dirname + '/cscps/images/' for the base option and <img src="aaa.bmp"> to reference to an image.

marcbachmann avatar Mar 08 '17 16:03 marcbachmann

Hi marcbachmann,

I set an svg image in header and it is not showing after converting it to pdf. But body elements are taking the images properly.

Please find the below and confirm that this is possible or not.

{ "format": "A4", "type": "pdf",
"base":"file://" + __dirname+"/template/images/", "header": { "height": "50px", "contents": '

' }, "footer": { "height": "30px", "contents": ''
} };

Also i set some dummy div for cache purpose.

Im using 2.1.0 latest version.

I have tried to set data uri of svg as well. That is not working too.

Please let me know if it is possible set image in header.

ndevendh avatar Mar 18 '17 15:03 ndevendh

<div><img src="icon_logo.vg"/></div>

ndevendh avatar Mar 18 '17 15:03 ndevendh

dummy div

<div class="dummy_img"><img src="icon_logo.vg"/></div>

ndevendh avatar Mar 18 '17 15:03 ndevendh

Still not working for me. My Code:

var pdf = require('html-pdf');
var html = fs.readFileSync('./Media/index.html', 'utf8');
var _basePath = 'file:///' + __dirname + '\\Media\\';
var options = {
    format: 'A4',
    base: _basePath
};

pdf.create(html, options).toFile('./Media/123.pdf', function (err, res) {
    if (err) return console.log(err);
    console.log(res); // { filename: '/app/businesscard.pdf' } 
});

HTML: <img src="logo.png" alt="Logo" />

Hardik21 avatar Apr 27 '17 12:04 Hardik21

It seems that for now the nesting an <img> tag inside a <div id="pageHeader"></div>, whether you actually have the HTML in your .html file or set the HTML in the header content option, doesn't render images. The best solution I've come up with after reading around a bit was what I have below. I used relative paths on images for the src attribute.

HTML

<div class="header-wrapper">
    <div>
        <img class="logo" src="/relative/path/to/header/image.png" />
    </div>
</div>

CSS

html, body {
    margin: 0;
    padding: 0;
    -webkit-print-color-adjust: exact;
}

.page {
    height: 100vh;
    page-break-after: always;
}

.page:last-of-type {
    page-break-after: auto
}

.page .header-wrapper {
    margin-top: 20px;
}

.page .header-wrapper > div {
    position: relative;
    width: 100%;
    text-align: center;
}

.page .header-wrapper > div .logo {
    width: 100%;
}

.page .page-body-wrapper {
    margin-top: 40px;
}

.page-body {
    font-family: Calibri, Candara, Segoe, Segoe UI, Optima, Arial, sans-serif;
    font-size: 10px;
}

Note: You must put the header on EVERY PAGE. If you don't, the image will not render on every page. Moreover, if you're turning the HTML file into a giant string on the server side, the image path should be relative to the HTML file in which you're trying to insert the image, NOT relative to the, say, server file that may be inserting the image dynamically into your HTML file.

Example folder structure:

app.js
app/
  pdf.html
  images/
     image-to-insert.jpg

What I did in app.js was the following:

const { body } = req,
		currentDir = `${__dirname}/`,
		template = `${currentDir}templates/pdf.html`;

let templateHtml = fs.readFileSync(template, 'utf8');

const headerImage = 'images/header.png';
	templateHtml = templateHtml.replace(/{{header}}/g, headerImage);

const baseFolder = './folder/',
	nameOfDocument = `PDF.pdf`,
	pdfDocument = `${baseFolder}/${nameOfDocument}`;

// If the folder doesn't exists, add it. Otherwise, skip it
if (!fs.existsSync(baseFolder)) { fs.mkdirSync(baseFolder); }

// Establish the base options for the PDF formatting
const options = {
	base: `file://${currentDir}`,
	// Height of document
	height: '11in',
	// Width of document
	width: '8in',
	// Border 'padding'
	border: {
		top: '0in',
		right: '0.5in',
		bottom: '0in',
		left: '0.5in'
	},
	header: {
		height: '0mm'
	},
	// Footer contents
	footer: {
		contents: '<div>This is a footer</div>'
	}
};

pdf.create(templateHtml, options).toFile(pdfDocument, (err, res) => {
	if (err) { return console.log(err); }
});

and in pdf.html, every page has the following

<style>
    html, body {
        margin: 0;
        padding: 0;
        -webkit-print-color-adjust: exact;
    }

    .page {
        height: 100vh;
        page-break-after: always;
    }

    .page:last-of-type {
        page-break-after: auto
    }

    .page .header-wrapper {
        margin-top: 20px;
    }

    .page .header-wrapper > div {
        position: relative;
        width: 100%;
        text-align: center;
    }

    .page .header-wrapper > div .logo {
        width: 100%;
    }

    .page .page-body-wrapper {
        margin-top: 40px;
    }

    .page-body {
        font-family: Calibri, Candara, Segoe, Segoe UI, Optima, Arial, sans-serif;
        font-size: 10px;
    }
</style>
<div class="page">
    <div class="header-wrapper">
        <div>
            <img class="logo" src="{{header}}" />
        </div>
    </div>
    <div class="page-body-wrapper">
        <div class="page-body">
           <p></p>
        </div>
    </div>
</div>

nickvirden avatar Dec 18 '17 04:12 nickvirden

hello i have facing the issue that , i takes the same values for two different pdfs i creates the caching issue in it, is it any way to reinitialize the html variables

pushkertiwari avatar May 22 '18 17:05 pushkertiwari

After 2 hours of trying in vain, I ended up generating my source HTML with base64 encoded images embedded in it (instead of using paths), and that worked on first try. So, if you have control over the HTML file you're trying to convert, this might be actually a lot simpler than trying to figure out what's wrong with your paths (which, as other issues show, has many possible pitfalls).

madve2 avatar Jul 18 '18 15:07 madve2

Your code should be

<div>
  <img src="aaa.bmp">
  <img src="bbb.bmp">
  <img src="ccc.bmp">
  <img src="ddd.bmp">
</div>
var options = { 
format: 'Letter',
base: 'file:///' + __dirname + '/images/'
}

Considering cscps is the root directory name.

rudrakshpathak avatar Sep 20 '18 08:09 rudrakshpathak

Image is not shown in pdf. Can anyone guide me? How can fix it?

Image Url :- https://www.codefire.org/sites/all/themes/codefire/img/logo.png

amitcodefire avatar Dec 05 '18 10:12 amitcodefire

Hi, you need to convert the image into base64 image. Following is the solution for the same.

Using css + images

It takes css into account. The only problem I faced - it ignored my images. The solution I found was to replace url in src attrribute value by base64, e.g.

<img src="data:image/png;base64,iVBOR...kSuQmCC">

You can do it with your code or to use one of online converters, e.g. https://www.base64-image.de/

Reference Link: https://stackoverflow.com/questions/14552112/html-to-pdf-with-node-js/14552323

krinjalpatel avatar Jun 24 '19 11:06 krinjalpatel

i convert my image into base64 using online converter . and use src

<img class="invoice-logo" alt="img-logo" src="data:image/jpeg;base64,/9j/4QAYRXhpZgAASUkqAAgAAAAAAAAAAAAAAP/sABFEdWNreQABAAQAAABkAAD/4QMqaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgY" />

shahnad avatar Jan 06 '22 13:01 shahnad

In my case following what @marcbachmann mentioned didn't work for some reason by setting a base property inside the options object maybe I messed up the path string! but what I did was I converted the images to a base64 strings with node and by using base64 instead is working like a charm.

if you have access to where the images are you can easily convert it with node without any additional libraries like so:

const convertImageToBase64 = imgPath => {
  const imgExtension = imgPath.split(".").pop();  \\ get image extension
  let image = `data:image/${imgExtenstion};base64`; \\ construct starting of the string needed by html img src
  image += fs.readFileSync(imgPath, 'base64'); \\ concat base64 string to the image string
  return image;
}

neenus avatar Jan 11 '23 19:01 neenus