Perform print operation on cups using Node.js

6k views Asked by At

I would like to print documents through http requests on Node.js. Is there any way to send print jobs and query CUPS server using Node.js. I found this project while exploring around, is it the only/correct way to do that??

2

There are 2 answers

0
tin On

You could use the shell to do so. I built a project some time ago where I needed to read certain hashtag from instagram and print the photos uploaded to IG with that hashtag using a raspberry pi and a photo printer.

var fs = require('fs'),
    exec = require('child_process').exec;

exec("lp /path/to/somepic.jpg");

// get printer jobs
exec("lpq",function (error, stdout, stderr) {
    console.log('stdout: ' + stdout);
    console.log('stderr: ' + stderr);

    if (error !== null) {
      console.log('exec error: ' + error);
    }
});

The command lp /path/to/somepic.jpg sends /path/to/somepic.jpg to the default printer. The command lpq displays the printer queue. For better use, read the CUPS documentation.

0
Rahul Bhooteshwar On

Following snippet seems useful. Not tried it as I am no longer working on this problem! It may be helpful for others. Original source: https://gist.github.com/vodolaz095/5325917

var ipp = require('ipp'); //get it from there - https://npmjs.org/package/ipp - $npm install ipp
var request = require('request'); //get it from there - https://npmjs.org/package/request - $npm install request
var fs = require('fs');

function getPrinterUrls(callback) {
    var CUPSurl = 'http://localhost:631/printers';//todo - change of you have CUPS running on other host
    request(CUPSurl, function (error, response, body) {
        if (!error && response.statusCode == 200) {
            var printersMatches = body.match(/<TR><TD><A HREF="\/printers\/([a-zA-Z0-9-^"]+)">/gm);//i know, this is terrible, sorry(
            var printersUrls = [];
            var i;
            if (printersMatches) {
                for (i = 0; i < printersMatches.length; i++) {
                    var a = (/"\/printers\/([a-zA-Z0-9-^"]+)"/).exec(printersMatches[i]);
                    if (a) {
                        printersUrls.push(CUPSurl + '/' + a[1]);
                    }
                }
            }
        }
        callback(error, printersUrls);
    });
};

function doPrintOnSelectedPrinter(printer, bufferToBePrinted, callback) {
    printer.execute("Get-Printer-Attributes", null, function(err, printerStatus){
        if(printerStatus['printer-attributes-tag']['printer-state']=='idle'){
            //printer ready to work
//*/
    printer.execute("Print-Job",
        {
            "operation-attributes-tag":{
                "requesting-user-name":"nap",
                "job-name":"testing"
            },
            "job-attributes-tag":{},
            data:bufferToBePrinted
        },
        function (err, res) {
            if (res.statusCode == 'successful-ok') {
                var jobUri = res['job-attributes-tag']['job-uri'];
                var tries = 0;
                var t = setInterval(function () {
                    printer.execute("Get-Job-Attributes",
                        {"operation-attributes-tag":{'job-uri':jobUri}},
                        function (err2, job) {
//                            console.log(job);
                            if (err2) throw err2;
                            tries++;
                            if (job && job["job-attributes-tag"]["job-state"] == 'completed') {
                                clearInterval(t);
//                                console.log('Testins if job is ready. Try N '+tries);
                                callback(null, job);//job is succesefully printed!
                            }
                            if (tries > 50) {//todo - change it to what you need!
                                clearInterval(t);
                                printer.execute("Cancel-Job", {
                                    "operation-attributes-tag":{
                                        //"job-uri":jobUri,  //uncomment this
//*/
                                        "printer-uri":printer.uri, //or uncomment this two lines - one of variants should work!!!
                                        "job-id":job["job-attributes-tag"]["job-id"]
//*/
                                    }
                                }, function (err, res) {
                                    if (err) throw err;
                                    console.log('Job with id '+job["job-attributes-tag"]["job-id"]+'is being canceled');
                                });

                                callback(new Error('Job is canceled - too many tries and job is not printed!'), null);

                            }
                        });
                }, 2000);
            } else {
                callback(new Error('Error sending job to printer!'), null);
            }
        });
//*/
        } else {
            callback(new Error('Printer '+printerStatus['printer-attributes-tag']['printer-name']+' is not ready!'),null);
        }
    });
}

function doPrintOnAllPrinters(data, callback) {
    var b = new Buffer(data, 'binary');
    getPrinterUrls(function (err, printers) {
        if (err) throw err;
        if (printers) {
            for (var i = 0; i < printers.length; i++) {
                var printer = ipp.Printer(printers[i]);
                doPrintOnSelectedPrinter(printer, b, callback);
            }
        } else {
            throw new Error('Unable to find printer. Do you have printer installed and accessible via CUPS?');
        }
    });
}

/*
 Example of usage
 */




fs.readFile('package.json', function (err, data) {
    doPrintOnAllPrinters(data, function (err, job) {
            if (err) {
                console.error('Error printing');
                console.error(err);
            } else {
                console.log('Printed. Job parameters are: ');
                console.log(job);
            }
        }
    );
});