devongovett / node-wkhtmltopdf Goto Github PK
View Code? Open in Web Editor NEWA wrapper for the wkhtmltopdf HTML to PDF converter using WebKit
A wrapper for the wkhtmltopdf HTML to PDF converter using WebKit
The current method for handling errors calls the callback (and kills the child process) on the first sight of an error, or even a warning.
This is an issue if it's a harmless warning and it would be better to let the child process run it's course.
This was an issue for us when we got the following warning:
QSslSocket: cannot resolve SSLv2_client_method
This warning did not prevent the creation of a PDF, but because node-wkhtmltopdf calls the callback when it sees an error, it led our next step in code to run before the PDF was saved.
I've made a fix and will submit it as a pull request, but you may have a different idea about how to solve this issue.
Thanks!
Could I get a new version number please? I'd like to specify a version in my package.json that includes the options.ignore functionality.
I know that I can pull the specific version I want via github links in my package.json, but that doesn't always work on some of the AWS servers I'm using.
Not sure why, but when attempting to pipe the output of the pdf to a file the file contents are truncated to almost nothing (47KB file to 20B of white space), and no error is output.
Doesn't work
wkhtmltopdf( html, { pageSize: 'letter' } ).pipe( writeStream );
Does work
wkhtmltopdf( html ).pipe( writeStream );
I was able to output to file directly with the output option no problem.
Hopefully saves someone else some trouble.
The page I would like to render to pdf is on a server that expects a JSON Web Token in the request HTTP header : x-access-token.
Is it possible to pass a x-access-token HTTP Header as an option to wkhtmltopdf along with the url?
I have experimented with the command line wkhtmltopdf using the --custom-header and --custom-header-propagation parameters and it works fine. However, I am not able (or don't know how) to pass these to the wkhtmltopdf node wrapper.
Stephen..
when specifying allow: ['foo', 'bar'] in options, the resulting parameter conversion is
--allow "foo" "bar" instead of --allow "foo" --allow "bar"
Hey bud,
Here is an error appearing when we use this module:
Oct 22 20:12:08 - ERROR - uncaughtException - Error: QSslSocket: cannot resolve SSLv2_client_method
at Socket.<anonymous> (/opt/webapp/node_modules/wkhtmltopdf/index.js:79:17)
at Socket.g (events.js:180:16)
at Socket.emit (events.js:95:17)
at Socket.<anonymous> (_stream_readable.js:764:14)
at Socket.emit (events.js:92:17)
at emitReadable_ (_stream_readable.js:426:10)
at emitReadable (_stream_readable.js:422:5)
at readableAddChunk (_stream_readable.js:165:9)
at Socket.Readable.push (_stream_readable.js:127:10)
at Pipe.onread (net.js:528:21)
I think it's just a warning tho.
https://github.com/devongovett/node-wkhtmltopdf/blob/master/index.js#L160
data
is not defined.
Version - wkhtmltopdf 0.12.2-6a13a51
OS - Windows 8.1 x64
I am writing an application that generates a pdf with a header and a footer. The library and this wrapper were working previously and successfully generated my PDF, but for some reason the paths I am sending are being converted from file://
protocol to http://
These are the options I am passing
var content = 'file:///E:/absolute/path/to/content.html';
var header = 'file:///E:/absolute/path/to/header.html';
var footer = 'file:///E:/absolute/path/to/footer.html';
var options = {
headerHtml: header,
footerHtml: footer,
toc: true,
noStopSlowScripts: true,
};
wkhtmltopdf(content, options).pipe(res);
I modified the wrapper so I can see what output the wkhtmltopdf library was printing
line 51
child.stderr.on('data', function(data) {
console.log(data.toString());
});
Which results in this output
Loading pages (1/6)
[> ] 0%
[=> ] 2%
[===> ] 5%
[====> ] 7%
[======> ] 10%
Error: Failed loading page http:///E:/absolute/path/to/header.html" (sometimes it will work just to ignore this error with --load-error-handling ignore)
Error: Failed loading page http:///E:/absolute/path/to/footer.html" (sometimes it will work just to ignore this error with --load-error-handling ignore)
Error: Failed loading page http:///E:/absolute/path/to/header.html" (sometimes it will work just to ignore this error with --load-error-handling ignore)
Error: Failed loading page http:///E:/absolute/path/to/footer.html" (sometimes it will work just to ignore this error with --load-error-handling ignore)
Exit with code 1 due to network error: HostNotFoundError
Notice how the paths with file://
are replaced with http://
After adding a few more lines to debug, I found the wrapper is generating this command. Which when executed directly, works as expected.
wkhtmltopdf --header-html "file:///E:/absolute/path/to/header.html" --footer-html "file:///E:/absolute/path/to/footer.html" toc --no-stop-slow-scripts file:///E:/absolute/path/to/content.html -
As mentioned, running the above command directly works fine, so I am thinking that sometime between my invocation of the library and it's execution, the parameters are modified.
Are there any glaring issues with my approach? Any help is appreciated.
Hi,
Pdf is generated fine without giving headerHtml, footerHtml. Also headerCenter works fine, but headerHtml with a url doesn't produce any output. The error (code) returned is : [Error: QNetworkAccessFileBackendFactory: URL has no schema set, use file:// for
files]. Can you please help? Thanks!
I'm trying to invoke the --javascript-delay
parameter, like so:
wkhtmltopdf(html, { javascriptDelay: 500 }).pipe(stream);
It throws an error:
[Uncaught Exception] Error: write EPIPE
at errnoException (net.js:901:11)
at Object.afterWrite (net.js:718:19)
Hi,
How I may run wkhtmltopdf from node wrapper with additional parameters like:
--footer-font-name
--footer-font-size
--footer-center?
I've remote URL such as this one.
However when I'm downloading, it's showing the following warnings:
Loading pages (1/6)
Warning: Failed to load file://cdn.optimizely.com/js/653710485.js (ignore)
Warning: Failed to load file://pagead2.googlesyndication.com/pagead/js/google_top_exp.js (ignore)
Warning: Failed to load file://www.google-analytics.com/analytics.js (ignore)
Warning: Failed to load file:///images/filetypes/pdf.png (ignore)
Warning: Failed to load file:///images/filetypes/txt.png (ignore)
Warning: Failed to load file://www.googletagservices.com/tag/js/gpt.js (ignore)
Warning: Failed to load file://connect.facebook.net/en_US/sdk.js (ignore)
The files in the source are like:
<script src="//cdn.optimizely.com/js/653710485.js">
<script src="//pagead2.googlesyndication.com/pagead/js/google_top_exp.js">
<img src="/images/filetypes/txt.png">
Is there any way that wkhtmltopdf
can assume automatically that these files are http by default (the same protocol as it's used during downloading)?
I am trying to include an html header and footer in my document.
The application I am building will take some an HTML template and output it as a PDF. Each page is to have a header and a footer.
Using the command line this looks like
wkhtmltopdf --html-header="C:\\fullpath\\header.html" --html-header="C:\\fullpath\\footer.html" mycompiledtemplate.html --output mynewpdf.pdft
Programmatically using node-wkhtmltopdf this looks like
var options = {
headerHtml: "C:\\fullpath\\header.html",
footerHtml: "C:\\fullpath\\footer.html",
};
wkhtmltopdf(html, options).pipe(res);
The first case outputs the expected pdf. The second case streams a corrupted pdf that doesn't load.
When I don't include a header or a footer, the document is rendered properly.
Are there any glaring issues with my implementation?
This is my header
<!DOCTYPE html>
<html>
<head>
</head>
<body>
header
</body>
</html>
This is my footer
<!DOCTYPE html>
<html>
<head>
</head>
<body>
footer
</body>
</html>
Any help would be appreciated. Thank you.
If you specify a file like so:
wkhtmltopdf('file://cv.html', { pageSize: 'a4' })
Then wkhtmltopdf
will attempt to use file://cv.html
as input, when it should be using cv.html
.
Here is my script:
'use strict';
import Bluebird from 'bluebird';
import Boom from 'boom';
import * as _ from 'lodash';
import wkhtmltopdf from 'wkhtmltopdf';
import fs from 'fs';
import Request from 'request';
import success from '../../../../helpers/success';
function gatherPage1(file) {
return function() {
let url = `${this.setHeroHost}/callsheet/app/index.html#/front/${this.csId}?project_id=${this.projectId}`;
return new Bluebird(function(resolve, reject) {
let stream = wkhtmltopdf(url);
stream.pipe(file);
stream.on('end', resolve);
stream.on('error', reject);
});
}
}
function gatherPage2(file) {
return function() {
let url = `${this.setHeroHost}/callsheet/app/index.html#/back/${this.csId}?project_id=${this.projectId}`;
return new Bluebird(function(resolve, reject) {
let stream = wkhtmltopdf(url);
stream.pipe(file);
stream.on('end', function() {
file.end();
return resolve();
});
stream.on('error', reject);
});
}
}
function prepReply() {
return {'foo': 'bar'};
}
function error(err) {
console.log(err);
return Boom.badImplementation(err);
}
export default function(server) {
return (request, reply) => {
const aws = server.plugins['set-hero-aws'];
const setHeroURL = server.settings.app.sethero.host;
const callsheetId = request.params.callsheetId;
const projectId = request.params.projectId;
const file = fs.createWriteStream('/tmp/tmp54.pdf');
return Bluebird.bind({
csId: callsheetId,
projectId: projectId,
setHeroHost: setHeroURL
})
.then(gatherPage1(file))
.then(gatherPage2(file))
.then(prepReply)
// .catch(error)
.done(success(reply, 201));
}
}
If I comment out the gatherPage2(file)
call in the thenable chain, then my API endpoint will resolve with the (for now) response of {'foo': 'bar'}
, but for whatever reason, when I add in the call to get the second page, the endpoint never resolves.
Anyone else run into this?
wkhtmltopdf in nodejs doesn't use print styles at all... It doe's print the page but doesn't use any of print styles....
I'm specifying the stylesheet for a table of contents using the following as my options argument:
var options = {
toc: true,
xslStyleSheet: "./toc_styles.xsl"
};
This generates the following error from the wkhtmltopdf
command:
Error: --xsl-style-sheet specified in incorrect location
It seems that the --xsl-style-sheet
argument has to be after the toc
argument in order to work.
Using this module with wkhtmltopdf
on Fedora 21, the following error surfaces
events.js:72
throw er; // Unhandled 'error' event
^
Error: libpng warning: iCCP: Not recognizing known sRGB profile that has been edited
at Socket.<anonymous> (/home/user/Conjuror/node_modules/wkhtmltopdf/index.js:79:17)
at Socket.g (events.js:180:16)
at Socket.emit (events.js:95:17)
at Socket.<anonymous> (_stream_readable.js:765:14)
at Socket.emit (events.js:92:17)
at emitReadable_ (_stream_readable.js:427:10)
at emitReadable (_stream_readable.js:423:5)
at readableAddChunk (_stream_readable.js:166:9)
at Socket.Readable.push (_stream_readable.js:128:10)
at Pipe.onread (net.js:529:21)
However, the PDF seems to be generated just fine and dandy. Seems like this should maybe be supressed.
Hi,
I am trying to convert an html to pdf using wkhtmltopdf.
My wkhtmltopdf version is wkhtmltopdf 0.12.3.2 (with patched qt)
My command is : wkhtmltopdf http://google.com file://C:/Users/
I am getting error as :
Error: Failed loading page http://google.com (sometimes it will work just to ignore this error with --load-error-handling ignore)
Exit with code 1 due to network error: HostNotFoundError
Kindly help me out to remove this error.
Similar to #13
Some command line options don't use dashes, but there is no syntax in this plugin to support these cases.
I propose this workaround or something similar
if (/toc/.test(key)) {
key = slang.dasherize(key);
} else {
key = key.length === 1 ? '-' + key : '--' + slang.dasherize(key);
}
Hi,
Is any way to convert local HTML page to PDF without any web server? Page have linked CSS and some *.png files. I can do this from command line.
It's quite an important part, the binary. I'm very surprised there's no output of any sorts when there's no wkhtmltopdf binary in the $PATH. Please add it to the code.
From what I've gathered this is a warning originating from Qt. It doesn't seem to impact the generation and running wkhtmltopdf from the command prompt it continues and just displays a warning. When I disable the error checking code the PDF generates and comes back fine.
I haven't been able to find a good way to distinguish between errors and warnings from wkhtmltopdf. I've solved it in my fork but not in a way I'm satisfied with:
https://github.com/pbaehr/node-wkhtmltopdf/blob/master/index.js#L65
Not sure if you can think of a better way of selectively deciding whether or not to bail on errors. I didn't open a pull request because a more general approach probably makes more sense. I'm not sure how many other warning conditions are being handled as errors here.
If I try to use this on my windows machine I keep getting enoent spawn.
I managed to hack around it by changing wkhtmltopdf.command to be the full path, instead of relaying on the path environment variable (ie wkhtmltopdf.command = 'C:/wkhtmltopdf/bin/wkhtmltopdf.exe'; )
I use node-wkhtmltopdf in meteor.js
I have a problem with General Options
Here is ma code:
this.route('pdfFile', {
where: 'server',
path: '/test.pdf',
action: function() {
// This action function allows you to edit the response buffer.
// create some http buffers for your pdf file
var headers = {
'Content-type': 'application/pdf',
'Content-Disposition': "attachment; filename=test.pdf"
};
// Add the headers to the response buffer
this.response.writeHead(200, headers);
// Load the wkhtmltopdf module.
// Notice we are using Meteor.npmRequire here, available trough the meteorhacks:npm module.
var wk = Meteor.npmRequire('wkhtmltopdf');
// Render the html response of 'http://www.google.com' to the response buffer.
var r = wk("http://10.11.12.13:3000/repertorium/insert", { pageSize: 'letter' }).pipe(this.response);
}
});
})
I use pageSize: 'letter' from General Option its works but i don
t know how to add another General Option exp. "--user-style-sheet"
THX
Is there a client-side version of this or someway to run it in browser for other users without a command line?
e.g:
child.stderr.on('data', function(data) {
console.log(data.toString());
});
child.stdout.on('data', function(data) {
console.log(data.toString());
});
This error is also not being reported.
This is something that would help people debug the issue with export DISPLAY=0:0 and running as a different user than the current X's one.
Please add this debugging message to the npm.
Thank you.
CSS IS NOT APPLYING
wkhtmltopdf('https://jaimegris.wordpress.com/2015/03/03/how-to-install-wkhtmltopdf-in-centos-6-5/', { pageSize: 'letter' })
.pipe(fs.createWriteStream('out.pdf'))
You currently are allowing for the parameter of --post but not actually using it correctly. You cannot send a post parameter encapsulated in quotations. An example:
wkhtmltopdf --post 'test hello' 'https://google.com' google.pdf
This will not work as the post param will fail. You must wrap only the value of the post param in quotations like so:
wkhtmltopdf --post test 'hello' 'https://google.com' google.pdf
This will submit correctly. This is also useful when you wish to send JSON strings (like I am sending in my request). I have attached below my solution to your code that will allow for POST params to be sent. However this solution will only allow for one post param currently but I believe that to be another issue with how your code operates. Let me know if you have any questions and I hope this is helpful :).
{"post": "json>>>>>hello"}
if (key !== 'toc' && key !== 'cover' && key !== 'page' && key !== 'post')
key = key.length === 1 ? '-' + key : '--' + slang.dasherize(key);
if (key == 'post') {
var postString = '';
var tempStrArr = val.split('>>>>>');
for (i = 0; i < tempStrArr.length; i++) {
if (i == 0)
postString += '--' + key;
if (i == 1 && i == tempStrArr.length - 1) {
postString += "'" + tempStrArr[i] + "'";
} else if (i == 1 ) {
postString += "'" + tempStrArr[1];
} else if (i == tempStrArr.length - 1) {
postString += " " + tempStrArr[i] + "'";
} else {
postString += ' ' + tempStrArr[i];
}
}
args.push(postString);
} else {
if (val !== false)
args.push(key);
if (typeof val !== 'boolean')
args.push(quote(val));
}
I need callback when it successfully create pdf. In this code there is no callback its take time to generate pdf . so i want when it done with all the file create then is send response
wkhtmltopdf(str)
.pipe(fs.createWriteStream(newPath+"/public/"+fileName));
@devongovett Could you take a few minutes and enable Travis CI for this repo? I think only the repo owner can do, I can't seem to enable Travis CI as a collaborator.
wkhtmltopdf(address, { output: filePath, windowStatus: 'abcd' }, function (err, signal) {
if (err) {
console.log(err)
return callback(err);
}
return callback(null, receipt, customer);
});
produces a
Error: Unknown long argument --window-status
Bug: uncaught exception when specifying toc parameter.
toc parameter (creates outlines from H tags) should be specified in special way:
wkhtmltopdf --title mypdf toc [option] <in> <outfile>
toc goes without --, and can have own parameter (option), or not. If toc goes without parameters it should go after (order matters) all other dashed -- parameters (elsewhere they will be parsed as toc params, as I caught). If specify toc now we'll have uncaught exception.
If do not add -- to toc in index.js, do not push value (if no options), push key after all other dashed params - it works as expected, the same as in shell (I checked).
So, the issue is only in proper parsing (maybe look in the underlying C library ?).
The underlying wkhtmltopdf tool is licensed GPLv3.
From https://en.wikipedia.org/wiki/MIT_License:
The MIT license is also compatible with many copyleft licenses, such as the GPL; MIT licensed software can be integrated into GPL software, but not the other way around.[4]
This works in 0.1.4 but is broke in 0.1.5. I believe a recent shell quoting update broke the url by leaving an extra \
in the url. Wkhtmltopdf program probably auto-url-encodes the url provided.
Original url passed to module:
http://localhost:3001/labels/551c4a9374fc5899129d6a2d?paper=5.5x8.5-sheet&start=1
Actual request to the web server from wkhtmltopdf:
http://localhost:3001/labels/551c4a9374fc5899129d6a2d?paper=5.5x8.5-sheet%5C&start=1
I haven't got time today, but I can probably look at fixing it when I get a chance.
I am trying to convert an html file with a simple svg embedded in it -
<svg width="200" height="200"> <circle fill="none" cx="100" cy="100" r="89" stroke="#aaa" stroke-width="20"></circle> <circle fill="none" cx="100" cy="100" r="89" stroke="#50a4e2" stroke-width="20" stroke-dasharray="559.2034923389832" stroke-dashoffset="223.68139693559328" transform="rotate(-90, 100, 100)"></circle></svg>
It should render something like this -
Basically just like this: http://explicate.blogspot.de/2011/01/multiple-html-files-to-single-pdf-with.html
I have problem with url query string. For example:
http://simpleurl.com/?arg1=adfa&arg2=abde
is passed to wkhtml without qouting - it contains special chars like '&' so it will not work correctly. On other hand in node-wkhtmltopdf code is following condition
var isUrl = /^(https?|file):///.test(input);
which will not work if quote url by myself .... I've already cope with that changing this line:
args.push(isUrl ? input : '-');
to something like that:
args.push(isUrl ? "'" + input + "'" : '-');
currently node-wkhtmltopdf calls out to a subprocess, it would probably be faster to use the cpp library directly
code and signal in callback parameter do not work
// Optional callback
wkhtmltopdf('http://google.com/', function (stream) {
stream.pipe(fs.createWriteStream('out.pdf'));
})
In this example, I have a simple HTML table that uses attributes to set the table border. I do not use an external css file. I generate a readable stream from wkhtmltopdf which is then passed to a streaming upload library, called s3-streaming-upload. The file is created, however the table borders are not visible.
HTML
<table border='10' frame='border' cellPadding='5%'>
<thead>
<tr>
<th> Foo </th>
<th> Bar </th>
</tr>
</thead>
<tbody>
<tr>
<td> hello </td>
<td> world </td>
</tr>
</tbody>
</table>
Node
var uploader = require('s3-streaming-upload').Uploader;
var readableStream = wkhtmltopdf(html, {});
var upload = new uploader({
accessKey: process.env.AWS_ACCESS_KEY_ID,
secretKey: process.env.AWS_SECRET_ACCESS_KEY,
bucket: process.env.APP_S3_BUCKET,
objectName: "test.pdf",
stream: readableStream,
debug: true
});
upload.send(function (err) {
});
Expected vs. Actual
I wanted page numbers in my footer, so I did
wkhtmltopdf(html, {
"footer-right": "[page]/[toPage]"
}).pipe(res);
This could be accomplished by chaining line 26 in index.js from
val = '"' + val.replace(/(["\\$`])/g, '\\$1') + '"';
to
val = val.replace(/(["\\$`])/g, '\\$1');
Good idea or is the value enclosing with double quotes there for a reason?
Following code snippet downloads an empty pdf, but when i give it the output parameter the file is created with correct content.
wkhtmltopdf('https://google.com/', { pageSize: 'letter' }).pipe(res);
Hello,
I've upgraded from a very old version to the latest version 0.3.1 of node-wkhtmltopdf on my Mac (OS X El Capitan 10.11.4), and now when i execute this command:
wkhtmltopdf("https://www.google.com", {debug:1}).pipe(res);
It generates the error:
[node-wkhtmltopdf] [debug] /bin/bash: cat: command not found
and the pdf cannot be retrieved.
It seems that /bin/sh
was changed to /bin/bash
few versions ago and it looks to have broken the Mac support. Note that my "old" version of node-wkhtmltopdf was correctly working before.
Quick fix would just to update this portion of code with darwin platform:
if (process.platform === 'win32') {
var child = spawn(args[0], args.slice(1));
} else if (process.platform === 'darwin') {
// Mac support
var child = spawn('/bin/sh', ['-c', args.join(' ') + ' | cat ; exit ${PIPESTATUS[0]}']);
}else{
// this nasty business prevents piping problems on linux
// The return code should be that of wkhtmltopdf and not of cat
// http://stackoverflow.com/a/18295541/1705056
var child = spawn('/bin/bash', ['-c', args.join(' ') + ' | cat ; exit ${PIPESTATUS[0]}']);
}
Thank you!
When I convert an html to pdf using wkhtmltopdf on the command line tool, it takes under one second. When I convert the same html file using using this library, it takes around 6-7 seconds. Is there a way we can get better performance? Am I missing anything obvious? The html file is on the same server hard disk.
The stream accessed in this calling pattern:
wkhtmltopdf('http://google.com/', { pageSize: 'letter' }, function (err, stream) {
// do whatever with the stream
});
does not work. Moreover, when logging the stream
to the console, the stream also has the readable
prop as false.
Hi @devongovett,
The company I work for @Woorank, uses the very useful node-wkhtmltopdf
NPM package and we were wondering about the status of this repository.
We needed to fix the issue where QTWebkit warning were considered like errors and made the process exit with a code 1. The following pull request: #58, made by user @zxlin fixes this issue but hasn't been merged or commented on since it was created a little more than a month ago.
If you don't have time to work on the project anymore would you consider transferring the project to us?
We actively use it in our infrastructure so we're also interested in extending and supporting it.
I hope you'll consider this request!
Have a nice day,
Mickael
I installed on my machine the pkg from the main wkhtmltopdf site. If i run the command from terminal it succesfully generate PDF.
The problem is that using your wrapper on node result in this error:
Uncaught node.js Error
Error: /bin/sh: wkhtmltopdf: command not found
at Socket.<anonymous> (/Users/ale/Downloads/node-webkit-v0.10.5-osx-x64/copia&incolla.app/Contents/Resources/app.nw/node_modules/wkhtmltopdf/index.js:79:17)
at Socket.g (events.js:196:16)
at Socket.EventEmitter.emit (events.js:104:17)
at readableAddChunk (_stream_readable.js:156:16)
at Socket.Readable.push (_stream_readable.js:123:10)
at Pipe.onread (net.js:520:20)
Mac OSX 10.10 Yosemite.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.