PHP Print to Network Printer

ctwheels picture ctwheels · Dec 6, 2016 · Viewed 15.3k times · Source

What I'm trying to do

Print a PDF document on a network printer while passing printing parameters for things such as colour, orientation, duplex, etc.

More information

  • We have multiple network printers, for which the IPs are static and known (i.e. 192.168.0.10)
  • I found a document containing a list of parameters/options that can be passed to the printer for changing print settings here (most of which can be found on page 25)
  • We are creating a process by which we will be printing a document in black and white EXCEPT the second page. This means that the first page, as well as page 3 and beyond are printed in black and white; page 2 is to be printed in colour. (This is due to cost of colour printing, plus our other pages don't contain colour, so printing them in colour is EXTREMELY pointless and approx. 8x more expensive - This process will be printing thousands of pages each month, which adds up to a lot of $$$)

What I've been somewhat successful with

I logged into one of the printers (192.168.0.10 - Ricoh MP C5503 [if you really must know]) and added FTP access

Printing a document using the command prompt in Windows works!

> ftp 192.168.0.10
> User (192.168.0.10:(none)): username
> Password: password
> put path\to\file.pdf filetype=PDF
> bye

What I've tried to do

Attempt 1 using PHP's exec() function

I've tried MANY ways to make exec work, but to no avail. I have not been able to run multiline commands using PHP's exec function (ideally, running the following). When running the following inside exec(), I am unable to connect to FTP since each line must be executed after the previous line has run. I have found nothing online (multiple Google searches yield no results [except how to echo multiple output lines from cmd - not how to insert multiple cmd lines consecutively])

> ftp 192.168.0.10
> User (192.168.0.10:(none)): username
> Password: password
> put path\to\test.pdf filetype=PDF
> bye

Attempt 2 using PHP's exec() function

I attempted to run the ftp command by passing a text file as some answers on this post suggest. This solution does not work as expected. When running ftp -i -s:test.txt from a command prompt, this works; in PHP, it does not.

PHP File

exec("ftp -i -s:test.txt");

Text File (test.txt)

open 192.168.0.10
username
password
put test.pdf filetype=PDF
bye

Attempt 3 using PHP's FTP functions

What I can't figure out now, is how to send the file to the printer over ftp and how to set the printer settings

$ftp = [
    'server'   => gethostbyaddr('192.168.0.10'),
    'username' => 'username',
    'password' => 'password',
];
$conn = ftp_connect($ftp['server']);
$login = ftp_login($conn, $ftp['username'], $ftp['password']);
if (is_readable($file)) {
    if (ftp_put($conn, $file, $file, FTP_ASCII)) {
        echo 'Successfully executed command';
    }
    else {
        echo 'Failed execution of command';
    }
}
else {
    echo 'File is not readable';
}

Ideally...

I'm looking for a solution that would work on both Windows and Linux systems as we are also in the process of moving from IIS to NGINX (thank god...). The method that I believe would be the best implementation is using ftp for Windows and rcp or rsh for Linux (since the printer documentation I attached under More information in the What I'm trying to do section mentions these methods for print).

I'd also like if we did not have to generate txt files or some other file type in order to print these documents. Our users may be processing hundreds of files at once, which I understand we can uniquely name each txt file and then delete after the script has successfully run, although I'd much prefer a clean solution where we can pass in parameters such as printer (IP or name from gethostbyaddr() function), username, password, file to be printed, options (i.e. colour, duplex, filetype, orientation, binding, etc.). We are using MPDF to generate our PDF files, so a method that would place the file without actually creating it on our server where we would then have to delete it would be preferred (i.e. MPDF string attachment for email) but these are not required.

Additionally

The solution must work with PHP.

I will continue to investigate more methods for printing documents on network printers after I post this until a viable solution has been found and update my post accordingly following each attempt.

Any help regarding this is greatly appreciated.



Edits


Unsuccessful methods

Method: PHP Printer functions

The printer functions do allow for printing, however they do not allow for control over the print jobs (options such as color/black and white printing, filetype, duplex, etc.). Thus, this options (unless someone has a "hack", will not work)

Method: JavaScript/AJAX

Although JavaScript/AJAX would work for printing (and allow print settings), we will be processing potentially hundreds of pages at once and the processing may be pushing print jobs to multiple printers (i.e. in different offices). The idea is to automate our printing for this process and for future processes alike.


Untested methods

Methods: Not yet tested


Solution?

I ended up creating a C# script to accomplish everything I needed to do. Since my requirements are fairly specific with regards to print settings, here's a link to Microsoft's System.Drawing.Printing namespace. Using this namespace, I was able to create appropriate methods for my needs. A few StackOverflow questions/answers below that provide more details on usage:

How to run C# in PHP? That's up to you. You can interface with a C# API (having C# run on another web server for example), reference the .NET DLL, use PeachPie, or inject declarations at runtime.


You may also be able to conjure up something using PowerShell (see PrintManagement documentation here). This would allow you to run the script using exec() - see this question regarding the execution of PowerShell from PHP.

Answer

Rei picture Rei · Dec 14, 2016

Try this:

$ftp = ftp_connect('192.168.0.10');
if(ftp_login($ftp,'username','password')){
    if(ftp_put($ftp,'filetype=PDF','yourfile.pdf',FTP_BINARY)){
        echo 'success';
    }
}

Let me know what you get.

Update: from the printer's manual on page 19, you can use the following command to send a file and set the device options at the same time:

ftp> put file1 filetype=postscript,tray=tray1,copies=3,resolution=600

In that example, file1 is the local file name that you want to send, filetype=postscript,tray=tray1,copies=3,resolution=600 is the remote file name. To be precise, the actual FTP command is:

STOR filetype=postscript,tray=tray1,copies=3,resolution=600

Using PHP's FTP functions, the PHP code is:

ftp_put($ftp,'filetype=postscript,tray=tray1,copies=3,resolution=600','file1',FTP_BINARY);

Where $ftp is the connection handle from a successful call to ftp_connect().

Putting it to my first example, the code becomes:

$ftp = ftp_connect('192.168.0.10');
if(ftp_login($ftp,'username','password')){
    if(ftp_put($ftp,'filetype=postscript,tray=tray1,copies=3,resolution=600','file1',FTP_BINARY)){
        echo 'success';
    }
}

Give it a try.