wkhtmltopdf on nodejs generates corrupt pdfs - node.js

I am using wkhtmltopdf to generate pdfs in nodejs
Below is my sample code to generate pdf
var wkhtmltopdf = require('wkhtmltopdf')
, createWriteStream = require('fs').createWriteStream;
var r = wkhtmltopdf('http://www.google.com', { pageSize: 'letter' })
.pipe(createWriteStream('C:/MYUSERNAME/demo.pdf'));
r.on('close', function(){
mycallback();
});
The above code is generating corrupt pdfs. I could not figure out the issue.
Although when I generate pdfs using command prompt it is generating correctly
like when I use below code in windows command prompt
wkhtmltopdf http://www.google.com demo.pdf
I get correct pdf generated,sadly when I try to generate pdf in node environment, it generates corrupt pdfs.
Incase it helps I'm using wkhtmltopdf 0.11.0 rc2
Thanks in advance.

wkhtmltopdf for node has a bug for windows, so you can write a new one.
Like this:
function wkhtmltopdf(input, pageSize) {
var spawn = require('child_process').spawn;
var html;
var isUrl = /^(https?|file):\/\//.test(input);
if (!isUrl) {
html = input;
input = '-';
}
var args = ['wkhtmltopdf', '--quiet', '--page-size', pageSize, input, '-']
if (process.platform === 'win32') {
var child = spawn(args[0], args.slice(1));
} else {
var child = spawn('/bin/sh', ['-c', args.join(' ') + ' | cat']);
}
if (!isUrl) {
child.stdin.end(html);
}
return child.stdout;
}
// usage:
createWriteStream = require('fs').createWriteStream;
wkhtmltopdf('http://google.com/', 'letter')
.pipe(createWriteStream('demo1.pdf'));
wkhtmltopdf('<body>hello world!</body>', 'letter')
.pipe(createWriteStream('demo2.pdf'));
note: the param is now 'letter' not { pageSize: 'letter' }

Related

PDF to Image in node

I am using node-express and need to convert pdf into image in the server side.
Pdf-poppler is not working in linux and pdf-image happens to be not working as well.
Any alternate method how we can convert and save pdf to image in the backend.
Pdf-poppler use pdftocairo command provided by the poppler project. Since poppler did support Linux, you can install it by yourself.
For example, on ubuntu
apt-get install poppler-utils
then call pdftocairo command using the code below from Pdf-poppler.
const path = require('path');
const {execFile} = require('child_process');
const pdftocairoBin = '/usr/bin/pdftocairo';
const FORMATS = ['png', 'jpeg', 'tiff', 'pdf', 'ps', 'eps', 'svg'];
let defaultOptions = {
format: 'jpeg',
scale: 1024,
out_dir: null,
out_prefix: null,
page: null
};
function pdf2image(file, opts) {
return new Promise((resolve, reject) => {
opts.format = FORMATS.includes(opts.format) ? opts.format : defaultOptions.format;
opts.scale = opts.scale || defaultOptions.scale;
opts.out_dir = opts.out_dir || defaultOptions.out_dir;
opts.out_prefix = opts.out_prefix || path.dirname(file);
opts.out_prefix = opts.out_prefix || path.basename(file, path.extname(file));
opts.page = opts.page || defaultOptions.page;
let args = [];
args.push([`-${opts.format}`]);
if (opts.page) {
args.push(['-f']);
args.push([parseInt(opts.page)]);
args.push(['-l']);
args.push([parseInt(opts.page)]);
}
if (opts.scale) {
args.push(['-scale-to']);
args.push([parseInt(opts.scale)]);
}
args.push(`${file}`);
args.push(`${path.join(opts.out_dir, opts.out_prefix)}`);
execFile(pdftocairoBin, args, {
encoding: 'utf8',
maxBuffer: 5000*1024,
shell: false
}, (err, stdout, stderr) => {
if (err) {
reject(err);
}
else {
resolve(stdout);
}
});
});
};
Usage of pdf2image function
pdf2image('./input.pdf', {out_dir:'./', out_prefix:'ppp'});
may be you can try this bro:
Create an uploads folder & copy the sample.pdf file which you want to convert as png. since here I am only going to show you how to convert the pdf to png I am using the pdf as a static path you need to upload that pdf file via REST API.
Now open your app.js OR index.js file & paste the below code we are using the pdf2pic packages to covert the pdf pages to png images.
or you visit this link:
https://codinghub.medium.com/how-to-convert-pdf-file-pages-to-png-images-node-js-dccec010bf13

Passed function is not well-serializable

I am using Puppeteer to scrape the web from a file template that contains the data of an order.
For this, I am using a puppeteer evaluation function, which works correctly while the file is in .js
However, when the "pkg" package is used to compile the .exe file or evaluate to execute and initiate a return or error: "The passed function is not quite serializable!"
Below is the code:
const dados = {name: 'foo', year: 1}
await page.evaluate(dados => {
let dom = document.querySelector('body');
const tags = Object.keys(dados);
for (let i = 0; i < tags.length; i++) {
const tag = tags[i];
dom.innerHTML = dom.innerHTML.split(`{{${tag}}}`).join(dados[tag]);
}
}, dados);
I try to add --public argument with pkg.
Like: pkg start.js -t node14-win-x64 --public
Then I can freely use ElementHandle.evaluate( (elem)=> elem.textContent );
With the manual of pkg, the --public means that : speed up and disclose the sources of top-level project.
BTW
To fixup cannot find chrome binary file
browser = await puppeteer.launch({
executablePath: "node_modules/puppeteer/.local-chromium/win64-782078/chrome-win/chrome.exe"
});
(The path above can set anywhere as you like.)
To fixup start.exe cannot run
Sometime the output binary exe cannot executable. It
always popup a new cmd prompt window when we enter start.exe. (or just double click.)
Just delete the output exe then rerun pkg
Check the code whether is runnable with node start.js or not
The easiest solution for me is to wrap it with eval() :
async getText(selector: string) {
await this.page.waitForSelector(selector);
let text = await eval(`this.page.$eval('${selector}', el => el.textContent)`)
return text;
}
or this:
await eval(`this.page.evaluate(
(selector) => { (document.querySelector(selector).value = ''); },
selector);`);
I had this exact issue relating to puppeteer and pkg. For some reason pkg doesn't correctly interpret the contents of the callback. The solution that worked for me was to pass a string to evaluate rather than a function:
Change:
const dados = {name: 'foo', year: 1}
await page.evaluate(dados => {
let dom = document.querySelector('body');
const tags = Object.keys(dados);
for (let i = 0; i < tags.length; i++) {
const tag = tags[i];
dom.innerHTML = dom.innerHTML.split(`{{${tag}}}`).join(dados[tag]);
}
}, dados);
to
await page.evaluate(`
(() => {
const dados = {name: 'foo', year: 1};
let dom = document.querySelector('body');
const tags = Object.keys(dados);
for (let i = 0; i < tags.length; i++) {
const tag = tags[i];
dom.innerHTML = dom.innerHTML.split(`{{${tag}}}`).join(dados[tag]);
}
// return dom to do something with the data in node
return dom.innerHTML
})()`);
This answer on github suggests an alternative solution - using the pkg api to inject the callback at compile time, however it didn't work for me.

How to convert a PDF file with NodeJS + Unoconv

I need to convert a docx file to pdf but I don't know very well nodejs, however, I know that the following can be done:
There is a project called unoconv-worker and in it, there is a part where the following line appears:
var child = spawn ('unoconv', [
'--stdout',
'--no-launch',
'--format', job.outputExtension,
job.tempPath
]);
https://github.com/koumoul-dev/unoconv-worker/blob/master/route.js
In my terminal I can convert it in the following way and it works perfectly:
unoconv -f pdf --output="something.pdf" docxtoconvert.docx
However, I would like to give you a file that I gave you the route, so I tried it this way:
var filePath = "/tmp/docxtoconvert.docx";
var child = spawn ("unoconv", [
"-f",
"pdf",
"--output",
"/tmp/something.pdf",
filePath
]);
Output:
Unoconv converter received message on stderr function () {
if (arguments.length === 0) {
var result = this.utf8Slice(0, this.length);
} else {
var result = slowToString.apply(this, arguments);
}
if (result === undefined)
throw new Error('toString failed');
return result;
}
But it has not worked. Could you help me? Thank you
Lot of wrapper modules exists for unoconv that can solve your problem.
You can try this
https://www.npmjs.com/package/unoconv

nodejs get file character encoding

How can I find out what character encoding a given text file has?
var inputFile = "filename.txt";
var file = fs.readFileSync(inputFile);
var data = new Buffer(file, "ascii");
var fileEncoding = some_clever_function(file);
if (fileEncoding !== "utf8") {
// do something
}
Thanks
You can try to use external module, such as https://www.npmjs.com/package/detect-character-encoding
The previously mentioned module works for me too. Alternatively you could have a look at detect-file-encoding-and-language which I'm using at the moment.
Installation:
$ npm install detect-file-encoding-and-language
Usage:
// index.js
const languageEncoding = require("detect-file-encoding-and-language");
const pathToFile = "/home/username/documents/my-text-file.txt"
languageEncoding(pathToFile).then(fileInfo => console.log(fileInfo));
// Possible result: { language: japanese, encoding: Shift-JIS, confidence: { language: 0.97, encoding: 1 } }

nodejs child_process.spawn msdeploy.exe with space in dest site

I am trying to use child_process.spawn with msdeploy.exe to automate deployement of some applications in IIS.
Whenever i have a space in my dest site name this makes msdeploy crash.
var command = 'C:/Program Files/IIS/Microsoft Web Deploy V3/msdeploy.exe';
var args = [];
args.push('-verb=sync');
args.push('-source:iisApp=C:/Users/PATH_TO_DEPLOY/dist');
args.push('-dest:iisApp=Default Web Site/test');
var process = spawn(command,args);
process.stdout.on('data', function(data) { grunt.log.write(data) });
process.stderr.on('data', function(data) { grunt.log.error(data); });
process.on('exit', function(code) {
if (code !== 0) {
grunt.fail.warn('Something went wrong');
}
done();
});
I've tried some others alternative like put " '-dest:iisApp="Default Web Site/test"' but msdeploy give me an error too.
This error is like : Argument '"-dest:iisApp=Default Web Site/haha"' not recognized. All arguments must begin with "-" char.
When i try to escape the space char or put " like describe above this gave me a similar error.
Is this is a bug in nodejs ? Maybe i've made something wrong ?
Thank.
How to accomplish this:
var path = require('path');
var platform = require('platform');
var cp = require('child_process');
var full_cmd = '/path/to/dir with space/program.exe';
var cmd = '.' + path.sep + path.basename(full_cmd); // cannot include double quotes -- the work-around is to use the 'cmd_opts.cwd'
var cmd_args = ['"--import-path=/path/to/dir with space/import_file"']; // can wrap each with double-quotes (Windows only -- fails on Unix)
var cmd_opts = {
cwd: path.dirname(full_cmd),
encoding: 'utf8'
};
if (platform.os() === 'win32') {
cmd_opts.windowsVerbatimArguments = true;
}
var proc = cp.spawn(
cmd,
cmd_args,
cmd_opts
);
The only way this doesn't work is if 'program.exe' is named something like 'program name with space.exe'

Resources