Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

render a pdf with an image. img disappeared #436

Closed
immatt2015 opened this issue Aug 21, 2017 · 12 comments
Closed

render a pdf with an image. img disappeared #436

immatt2015 opened this issue Aug 21, 2017 · 12 comments

Comments

@immatt2015
Copy link

Chromium version: 62.0.3188.0,
Nodejs version: v8.4.0,
puppeteer version: 0.9.0;

I rendered a pdf with { printBackground: true } option, but the img not shown in the pdf.

@aslushnikov
Copy link
Contributor

Could you please share the page you try to print?

@vlad-zhukov
Copy link

When I do the following the logo is not rendered:

const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://google.com');
await page.pdf({path: './example.pdf', printBackground: true});

browser.close();

If I also add await page.emulateMedia('screen'); it renders fine.

@aslushnikov
Copy link
Contributor

Your script yields the following pdf for me without the emulateMedia command:

example.pdf

It could be that the logo is slow to load for you. Try navigating page with waitUntil: 'networkidle':

const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://google.com', {waitUntil: 'networkidle'}); // <== This should help
await page.pdf({path: './example.pdf', printBackground: true});

browser.close();

@vlad-zhukov
Copy link

@aslushnikov Why was it closed? I am able to consistently reproduce the issue in puppeteer@0.10 and Chrome@60 in the print preview dialog under both Windows 10 and Mac.

In my example I didn't notice but google.com redirected me to google.ru that has the issue. If I disable redirecting I get the same pdf as yours. It's actually bugged a bit too, note the missing 'apps' icon in the top right corner.

Reproduce in puppeteer

const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://google.ru'); // or 'https://google.de'
await page.screenshot({path: './example.png'});
await page.pdf({path: './example.pdf', printBackground: true}); // broken
await page.pdf({path: './example2.pdf', printBackground: true}); // fine

browser.close();

Screenshot renders fine, the 1st pdf has missing parts and the 2nd pdf is fine:
example.png
example.pdf
example2.pdf

Note: Adding {waitUntil: 'networkidle'} and await page.waitFor(30000) makes no difference as the page is obviously fully-loaded.

Reproduce in Chrome

Go to https://google.ru (or https://google.de), wait for the page to fully load and open the print dialog, a pdf in the preview has missing images. Changing settings and/or closing and opening the dialog again rerenders the pdf correctly.

My print dialog settings:

  • Margins: none
  • Scale: 100
  • Background graphics: checked

@aslushnikov aslushnikov reopened this Aug 25, 2017
@aslushnikov
Copy link
Contributor

I am able to consistently reproduce the issue in puppeteer@0.10 and Chrome@60 in the print preview dialog under both Windows 10 and Mac.

@vlad-zhukov does your windows machine have screen dpi > 1?
There are a bunch of media rules on the google.ru website that rely on dpi. By default, puppeteer emulates dpi 1. When I set dpi to 2, I get complete pdfs.

Here's the snippet that works for me:

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({headless: true});
  const page = await browser.newPage();
  await page.goto('https://google.ru', {waitUntil: 'networkidle'});
  await page.setViewport({
    width: 800,
    height: 600,
    deviceScaleFactor: 2,
  });
  await page.screenshot({path: './example.png'});
  await page.pdf({path: './example.pdf', printBackground: true});
  await page.pdf({path: './example2.pdf', printBackground: true});

  browser.close();
})();

Reproduce in Chrome

Go to https://google.ru (or https://google.de), wait for the page to fully load and open the print >dialog, a pdf in the preview has missing images. Changing settings and/or closing and opening the >dialog again rerenders the pdf correctly.

I can't repro this on Mac and Chrome 60.0.3112.113. The graphics always appears for me when the "print background" is checked and disappears when I uncheck.

@vlad-zhukov
Copy link

Thanks for looking into this.

I've investigated a little more and set a simple example locally that reproduces this bug in Google Chrome, puppeteer and other Chromium-based browsers (Opera, Vivaldi). In short it fails to render images that are inside of a -webkit-max-device-pixel-ratio media query. Setting dpi higher than stated in this query will skip this block and it will render fine.

I am personally not affected by the issue and don't want to spend time reporting it to the Chromium bug tracker and all that stuff, however I can setup a GitHub repo with a reproduction if somebody else wants to push the issue further. Anyway in my opinion this issue should stay open for better visibility.

@aslushnikov
Copy link
Contributor

however I can setup a GitHub repo with a reproduction if somebody else wants to push the issue further.

I'd appreciate that.

@conradkleinespel
Copy link

For anyone running into this issue, in my case, I had a self-signed SSL cert and by default Puppeteer won't load images for which there is an HTTPS error. So, for development purposes, I run Puppeteer like this:

puppeteer.launch({ignoreHTTPSErrors: true})
    .then(async browser => {
        // ...
    });

I will of course set ignoreHTTPSErrors to false in the production environment.

@chaelli
Copy link

chaelli commented Dec 10, 2019

I think this should be reopened. I have a case where a background image is not printed even with deviceScaleFactor: 2 - but it works if I generate the PDF a second time. The first time it always fails.
The image is partly displayed if I just create the pdf twice. It's completely displayed if I wait 2 seconds between the first and the second pdf-creation.

I can only imagine that the issue is with the switch to the print-css. And then there is no time to load the image that matches the new styles. This is confirmed as await page.emulateMedia('print'); solves the problem.

@aklef
Copy link

aklef commented May 7, 2021

If anybody ends up here because they couldn't get images to load in the html-node-pdf package, I worked around this issue by using the URL file method (directly passes throught to puppeteer) instead of the content method (which parses the html content with handlebars first).

@TheProgrammer21
Copy link

Does anyone know how to solve this?
When I use the headless: false option I see my website with the image loaded, but when I export the PDF the image is just the default icon for a non-loaded image:
image

My Code:

  const browser = await puppeteer.launch({ headless: false, args: ["--explicitly-allowed-ports=" + port] });
  const page = await browser.newPage();
  await page.setContent(sites[0].currentDraft!.content, { waitUntil: "networkidle0" });
  await page.waitFor(2000);
  await page.emulateMediaType("print");
  await page.pdf({ path: "F:\\Desktop\\file.pdf", format: "a4" });
  await browser.close();

I already tried media types "screen" and "print", both don't work. The HTML of the web page is:

<html xmlns="http://www.w3.org/1999/xhtml">
   <head></head>
   <body>
      <p>Es handelt sich hierbei um ein File!</p>
      <p><strong>File:</strong></p>
      <sm-file class="mceNonEditable" title="Bright Solutions _ Digitale Projekt-Checklisten.pdf" data-uuid="AD13E638-6DB5-4DCD-A7F6-03D66C1D24DF" data-name="Bright Solutions _ Digitale Projekt-Checklisten.pdf">
         <img src="http://localhost:6666/icon_file.svg" width="20px" height="20px" />
         <hr />
         Bright Solutions _ Digi... ten.pdf
      </sm-file>
      <p>Und hier kommt dann noch ein Bild hinzu!</p>
   </body>
</html>

Has anyone an idea why the image is not rendered?

@TheProgrammer21
Copy link

Does anyone know how to solve this?
When I use the headless: false option I see my website with the image loaded, but when I export the PDF the image is just the default icon for a non-loaded image:
image

My Code:

  const browser = await puppeteer.launch({ headless: false, args: ["--explicitly-allowed-ports=" + port] });
  const page = await browser.newPage();
  await page.setContent(sites[0].currentDraft!.content, { waitUntil: "networkidle0" });
  await page.waitFor(2000);
  await page.emulateMediaType("print");
  await page.pdf({ path: "F:\\Desktop\\file.pdf", format: "a4" });
  await browser.close();

I already tried media types "screen" and "print", both don't work. The HTML of the web page is:

<html xmlns="http://www.w3.org/1999/xhtml">
   <head></head>
   <body>
      <p>Es handelt sich hierbei um ein File!</p>
      <p><strong>File:</strong></p>
      <sm-file class="mceNonEditable" title="Bright Solutions _ Digitale Projekt-Checklisten.pdf" data-uuid="AD13E638-6DB5-4DCD-A7F6-03D66C1D24DF" data-name="Bright Solutions _ Digitale Projekt-Checklisten.pdf">
         <img src="http://localhost:6666/icon_file.svg" width="20px" height="20px" />
         <hr />
         Bright Solutions _ Digi... ten.pdf
      </sm-file>
      <p>Und hier kommt dann noch ein Bild hinzu!</p>
   </body>
</html>

Has anyone an idea why the image is not rendered?

0

The reason is ERR_UNSAFE_PORT! The port 6666 is considered unsafe. A full list of unsafe ports can be seen here: https://superuser.com/questions/188058/which-ports-are-considered-unsafe-by-chrome So just change the port of the webserver to something that is not on this list and everything works fine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants