Giter Site home page Giter Site logo

Comments (15)

westy92 avatar westy92 commented on May 11, 2024

If you specify a port and/or host in your options, it assumes Chrome is running on that port/host and tries to connect to it.

const options = {
  port: 9222, // port Chrome is listening on
};

Either run Chrome on that port or remove that line (port) and html-pdf-chrome will spawn its own instance and clean it up after. If you care about speed, I'd highly recommend keeping Chrome running in the background via pm2 or something similar. This removes the overhead of spawning and cleaning up Chrome every single time you wish to generate a PDF.

from html-pdf-chrome.

stephLH avatar stephLH commented on May 11, 2024

Thank you, it was quite obvious!
I also had to symlink the google-chrome path (/usr/bin/google-chrome-stable to usr/bin/google-chrome).

Now I dont have any error message left but I cannot find my PDF output.
I tried to force the path within the JS script but without success:
htmlPdf.create(html, options).then((pdf) => pdf.toFile('~/test.pdf'));
Any Idea for this issue too ?

I am also a beginner with the JS syntax...
How would you replace the "hello world" line in order to import a local html file you want to convert ?

Thanks very much! I will try to follow your advice and use pm2 as well.

from html-pdf-chrome.

westy92 avatar westy92 commented on May 11, 2024

Since you are working with Promises, you'll want to catch and log any errors:

htmlPdf.create(html, options)
  .then((pdf) => pdf.toFile('test.pdf'))
  .catch((err) => {
    console.log(err);
  });

The output file should be in the same directory you ran node test.js in.

If you want to use an external file, you could try loading the file into memory and then passing it as a string instead of the literal example HTML. I'd recommend using fs-extra.

const fs = require('fs-extra');
fs.readFile('file.html', 'utf8')
  .then((file) => htmlPdf.create(file, options))
  .then((pdf) => pdf.toFile('test.pdf'))
  .catch((err) => {
    console.log(err);
  });

from html-pdf-chrome.

stephLH avatar stephLH commented on May 11, 2024

I did not manage to produce a PDF file under Linux :-(
So I went back to windows, tried again with the same JS file and it works! (hello word example)
I have no idea why it failed (or I could not find the pdf file) under Linux...

I also tried your code to convert a local html file with fs-extra but it creates a blank empty pdf file.
Maybe is it linked to the landscape orientation of the html file ?

By the way, would you have a code example to specify print options ? Is it within the options json ?
I tried these (according to the file /lib/src/ChromePrintOptions.d.ts):

const options = {
	//port: 9222,
	landscape: true
};

and

const options = {
	//port: 9222,
	ChromePrintOptions: {
		landscape: true
	}
};

from html-pdf-chrome.

westy92 avatar westy92 commented on May 11, 2024

After putting the .catch() did it log an error?

The ChromePrintOptions require at least Chrome 60, as noted in this comment. google-chrome-beta is currently version 60, so you can install and use that if these options are a requirement.

You can find an example of these options in the unit tests.

from html-pdf-chrome.

stephLH avatar stephLH commented on May 11, 2024

Nope, no log with the .catch() option on Linux. (I can try again if you want)

Thanks for the link to the unit tests, it works perfectly! (Windows)

I am also wondering if the blank empty pages I had with my local file is caused by the CSS, which is not rendered.

from html-pdf-chrome.

westy92 avatar westy92 commented on May 11, 2024

Is your local HTML file referencing a local CSS file?

from html-pdf-chrome.

stephLH avatar stephLH commented on May 11, 2024

No, the CSS is embedded within the html file.
An exemple here.

It is an html ioslides presentation generated from rmarkdown.

When I open the html file with chrome, I can save it to pdf with the options (orientation, margin, etc...)

I also tried again the script from Linux:

const htmlPdf = require('html-pdf-chrome');

const html = '<p>Hello, world!</p>';

const options = {
};

htmlPdf.create(html, options)
  .then((pdf) => pdf.toFile('test.pdf'))
  .catch((err) => {
    console.log(err);
  });

I confirm you it does not create a pdf with no error message.

from html-pdf-chrome.

westy92 avatar westy92 commented on May 11, 2024

I believe you may have uncovered a bug (#12). I added a fix to the next release plan.

from html-pdf-chrome.

westy92 avatar westy92 commented on May 11, 2024

With the latest release (v0.2.0) you are able to pass in a local file path. See the unit tests for an example. This should fix your issue without needing to wait for me to fix the previously mentioned bug.

from html-pdf-chrome.

stephLH avatar stephLH commented on May 11, 2024

Thanks for the work on this issue!
I believe I need to learn JS because it's very difficult for me to even reproduce the unit tests.
I tried with a file located with the JS script in the same directory.

I tired this:

const HtmlPdf = require('html-pdf-chrome');

const options = {
};

const filePath = 'file.html';
const result = await HtmlPdf.create(filePath, {port});
expect(result).to.be.an.instanceOf(HtmlPdf.CreateResult);
const pdf = await getParsedPdf(result.toBuffer());
expect(pdf.getRawTextContent()).to.startWith('Passed!');

But I get this error:

const result = await HtmlPdf.create(filePath, {port});
                     ^^^^^^^
SyntaxError: Unexpected identifier
    at createScript (vm.js:56:10)
    at Object.runInThisContext (vm.js:97:10)
    at Module._compile (module.js:542:28)
    at Object.Module._extensions..js (module.js:579:10)
    at Module.load (module.js:487:32)
    at tryModuleLoad (module.js:446:12)
    at Function.Module._load (module.js:438:3)
    at Module.runMain (module.js:604:10)
    at run (bootstrap_node.js:389:7)
    at startup (bootstrap_node.js:149:9)

Do I need to remove await ?
If I also comment the expect lines and remove the port parameter, I also need to define the getParsedPdf function...

from html-pdf-chrome.

westy92 avatar westy92 commented on May 11, 2024

I did not mean to copy the unit tests exactly, but use their ideas. They are written in TypeScript but you are working with JavaScript. I took the liberty to synthesize an example for you below using a local file path.

const htmlPdf = require('html-pdf-chrome');
const path = require('path');

const options = {
  port: 9222, // port Chrome is listening on
};

const filePath = path.join('file://', __dirname, 'test.html');
htmlPdf.create(filePath, options)
  .then((pdf) => pdf.toFile('test.pdf'))
  .catch((err) => {
    console.log(err);
  });

If you require further assistance with JavaScript as a language and not this library, please ask on https://stackoverflow.com/.

from html-pdf-chrome.

gate5th avatar gate5th commented on May 11, 2024

@westy92 I apologize for opening this back up, but I'm not having any luck getting it to load a file. I'm assembling multi-page pdfs, and my methodology is essentially joining together several templates together into a single html page with each template as a iframe. At first I tried the long html string, which showed the ancillary information on the pdf but not the content from the iFrames, even when I added a timer to completion trigger:

const options = {
  // port: 9222 //port Chrome is listening on
  completionTrigger: new htmlPdf.CompletionTrigger.Timer(5000)
}

Then I saw that the long html string can cause an issue, so I refactored to create an HTML file first and then feed it as a parameter. But when provide the filePath as the first parameter I just get a blank pdf with the filename as text. Here's my code:

async chromeGeneratePDF(theHTML) {
    //receives HTML as string
    //then use html-pdf-chrome node package to convert to pdf

    const sessionID = this.resolveObject.sessionObject.sessionID;
    const insuredName = _.camelCase(this.resolveObject.sessionObject.questionsAnswered['first-named-insured'].answer);
    const formName = this.formName;

    // const pathToExistingHTMLFile = path.posix.basename('file:///' + __dirname + '/' + formName + '.html');
    const filePathOne = __dirname + '/' + formName + '.html';
    const filePathTwo = path.join('file://', __dirname, formName + '.html')
    const filePathThree = path.join('file:/', __dirname, formName + '.html')
    const filePathFour = path.join('file:', __dirname, formName + '.html')
    const filePathFive = path.join(__dirname, formName + '.html')


    const options = {
      // port: 9222 //port Chrome is listening on
      // completionTrigger: new htmlPdf.CompletionTrigger.Timer(5000)
    }

    let thePDF = await htmlPdf.create(filePathOne, options).then((pdf) => pdf.toFile(__dirname + '/' + `${insuredName}_${this.formName}_${sessionID}_filePathOne.pdf`)).catch((err) => console.log('PDF ERROR from htmlPdf for filePathOne:', err));
    let thePDFTwo = await htmlPdf.create(filePathTwo, options).then((pdf) => pdf.toFile(__dirname + '/' + `${insuredName}_${this.formName}_${sessionID}_filePathTwo.pdf`)).catch((err) => console.log('PDF ERROR from htmlPdf for filePathTwo:', err));
    let thePDFThree = await htmlPdf.create(filePathThree, options).then((pdf) => pdf.toFile(__dirname + '/' + `${insuredName}_${this.formName}_${sessionID}_filePathThree.pdf`)).catch((err) => console.log('PDF ERROR from htmlPdf for filePathThree:', err));
    let thePDFFour = await htmlPdf.create(filePathFour, options).then((pdf) => pdf.toFile(__dirname + '/' + `${insuredName}_${this.formName}_${sessionID}_filePathFour.pdf`)).catch((err) => console.log('PDF ERROR from htmlPdf for filePathFour:', err));
    let thePDFFive = await htmlPdf.create(filePathFive, options).then((pdf) => pdf.toFile(__dirname + '/' + `${insuredName}_${this.formName}_${sessionID}_filePathFive.pdf`)).catch((err) => console.log('PDF ERROR from htmlPdf for filePathFive:', err));

    return thePDF

  }

filePathOne and filePathFive produce pdfs with a single line of text showing the correct path to the file. Two, Three and Four all return totally blank pdfs. For Two and Five it appears htmlPdf.create just uses the path as a string, not recognizing that it's actually a file and using the file contents. I looked at the unit test and wasn't able to figure out how the method knows whether it's working with a file or a string. Is there a flag or something that should be added? Or a slightly different method, like htmlPdf.createFromFile?

P.S. I also tried putting the file in an variable and passing it to htmlPdf.create and got a blank pdf with [Object Object] so that didn't work either.

let theFile = await fs.createReadStream(filePathOne);
    let thePDF = await htmlPdf.create(theFile, options).then((pdf) => pdf.toFile(__dirname + '/' + `${insuredName}_${this.formName}_${sessionID}.pdf`)).catch((err) => console.log('PDF ERROR from htmlPdf for theFile:', err));

Any help would be greatly appreciated!

from html-pdf-chrome.

westy92 avatar westy92 commented on May 11, 2024

@gate5th my apologies for the delay! My schedule did not allow me to work on this project for a while.

I released a new version today, v0.4.1.

The code to determine if you are working with a file or a string is here:

const url = /^(https?|file|data):/i.test(html) ? html : `data:text/html,${html}`;

It just looks to see if it starts with http:, https:, file:, or data:.

You can find an example of generation from an external file here:

it('should generate a PDF from a local file', async () => {
const filePath = path.join('file://', __dirname, '../../test/test.html');
const result = await HtmlPdf.create(filePath, {port});
expect(result).to.be.an.instanceOf(HtmlPdf.CreateResult);
const pdf = await getParsedPdf(result.toBuffer());
expect(pdf.getRawTextContent()).to.startWith('Passed!');
});

from html-pdf-chrome.

westy92 avatar westy92 commented on May 11, 2024

If you or anyone needs additional help, please open a new issue with a specific question. Thank you!

from html-pdf-chrome.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.