ACEG
ACEG

Reputation: 2041

Puppeteer: cannot render pdf with images stored locally

I cannot get images stored locally to be rendered in generated pdf with Puppeteer, but external images for which I specify a url work.

In particular, in the sample code below, rendering the page in test_html1 works, while rendering the test_html2 does not work.

(async () => {
  const browser = await puppeteer.launch({ args: ['--no-sandbox'] });
  const page = await browser.newPage();
  const test_html1 = `<html><h3>Hello world!</h3><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/2/2f/Google_2015_logo.svg/1024px-Google_2015_logo.svg.png"></html>`;
  // const test_html2 = `<html><h3>Hello world!</h3><img src="file:///home/cristina/Documents/logo.jpg"></html>`;
  await page.goto(`data:text/html,${test_html}`, { waitUntil: 'networkidle0' });
  await page.pdf({ path: `${this.outputPath}/test-puppeteer.pdf`,
      format: 'A4', landscape: !data.isPortrait,
      margin: { top: '0.5cm', right: '1cm', bottom: '0.8cm', left: '1cm' }, printBackground: true });
  await browser.close();
})();

Result with test_html1:

enter image description here

Result with test_html2:

enter image description here

My questions:

Upvotes: 1

Views: 7967

Answers (3)

Mehedi Hasan Shifat
Mehedi Hasan Shifat

Reputation: 720

If anyone still facing the issue in 2023 - "puppeteer is not able to load the images or files from relative path" then here is a solution I have find out.

You can run a http server in pm2 or something like that. And then specify the file base url after creating the page in puppeteer.

Dependency :

    "dependencies" : {
        "http-server": "^14.1.1"
    }

Run a http server : pm2 start http-server -- ./server -p 9453 -c-1

specify the path in puppeteer : await page.goto(http://localhost:9453/images)

Here is a full code version :

        const browser = await puppeteer.launch({
            protocolTimeout: 120 * 1000,
            executablePath: process.env.PUPEETER_EXECUTABLE_PATH,
            headless: true,
            args: ['--no-sandbox', '--disable-web-security', '--js-flags="--max-old-space-size=2048"', '--debug-print']
        });

        const page = await browser.newPage();

        await page.goto(`${process.env.FILE_SERVER_URL}:${process.env.FILE_SERVER_PORT}/${directMail.id}/`);

        const viewportOption = viewPortOptions[0];

        console.log(`Direct Mail ID : ${directMail.id} | Viewport option `, viewportOption)

        await page.setViewport(
            viewportOption
        );

        await page.setContent(directMail.templateHtmlStringUpperPart + concatenatedUsersTemplateHtml + directMail.templateHtmlStringLowerPart,
            {
                waitUntil: 'networkidle0'
            });

Upvotes: 0

HEMAL
HEMAL

Reputation: 430

function base64_encode(file) {
var bitmap = fs.readFileSync(file);
return new Buffer(bitmap).toString('base64');
}
img.src = 'data:image/png;base64,' + base64_encode(imagePath);

You can use above function it's render very fast.

Upvotes: 0

ACEG
ACEG

Reputation: 2041

Solved on Puppeteer GitHub: https://github.com/GoogleChrome/puppeteer/issues/1643

Basically, it doesn't work because, as a security measure against malicious websites, access to local images is blocked.

Upvotes: 1

Related Questions