Print to network printer from PHP - php

What is the best approach for printing (an existing pdf, in my case) to a LAN printer directly from php? So far I have been unsuccessful in getting anything to work, but I'm not sure what direction to further pursue. I am running Apache on Windows SBS 2008, PHP 5.3.9.
Approaches I know of so far:
shell_exec()
phpprintipp - this seems like the best approach to me if I could get it to work
php_printer.dll - no current dll exists
It seems like this should be a simple task that has a widely accepted approach, but so far I'm not finding it. Thanks!

This is a tough nut to crack. I've had my own adventures in Windows printing from Ruby and came up with a few potential solutions that work by invoking an external command, which in PHP-land is system() or exec() (don't forget escapeshellcmd()/escapeshellarg()—they tend to make this stuff easier, especially on Windows). All of them assume Windows knows about the printer and it can be referenced by name.
You can literally just redirect the file to the networked printer, e.g.:
copy /b \path\to\filename.pdf > \\Printer_Machine\Printer_Queue
The /b switch specifies a binary file, but I'm 80% sure it's not strictly now,
in 2012.
You can try the print command:
print /d:\\Printer_Machine\Printer_Queue \path\to\filename.pdf
\d stands for "device." I haven't actually tried this one and I'm not sure if it
works with PDF or only, owing to its DOS origins, text files.
Install Adobe Reader and use its command line facilities:
AcroRd32.exe /t \path\to\filename.pdf "Printer Name" "Driver Name" "Port Name"
I'm not sure if your server environment can accommodate Reader but this is the
solution I've been most successful with. You can find
documentation here
(PDF, pg. 24). Printer Name and Driver Name should match exactly what you see in the
printer's properties in Control Panel. Port_Name can usually be omitted, I think.
Print using Ghostscript. I've never tried this on
Windows but the
documentation is here
and there's
more info here. The
command goes something like this:
gswin32.exe -sDEVICE=mswinpr2 -sOutputFile="%printer%Printer Name" \path\to\filename.pdf
mswinpr2 refers to Windows' own print drivers (see the second link above),
"%printer%" is literal and required and "Printer Name" should, again, match the
printer's name from Control Panel exactly. Ghostscript has many, many options and
you'll likely have to spend some time configuring them.
Finally, a general tip: You can register a network printer with a device name with the net use command e.g.:
C:\> net use LPT2 \\Printer_Machine\Printer_Queue /persistent:yes
This should let you use LPT2 or LPT2: in place of \\Printer_... with most commands.
I hope that's helpful!

Not sure if this works for all printers but this gets the job done sending ZPL files to a Zebra label printer:
<?php
if(($conn = fsockopen('192.168.10.112',9100,$errno,$errstr))===false){
echo 'Connection Failed' . $errno . $errstr;
}
$data = <<<HERE
^XA
^FT50,200
^A0N,200,200^FDTEST^FS
^FT50,500
^A0N,200,200^FDZebra Printer^FS
^XZ
HERE;
#send request
$fput = fputs($conn, $data, strlen($data));
#close the connection
fclose($conn);
?>

Related

PHP: How to transfer files from IBM (Unix) filesystem to Windows network share?

We have a Windows network share of say \\share\drive, but if I try to save to that in PHP it just tells me directory not found (though it works from my Windows box).
Our IBM guy says it should work but it doesn't... I've tried various combinations and I have no examples in our PHP code of anything doing this (to any share).
$share = '\\\\share\\drive'; // or '//share/drive'
file_put_contents($share, 'blah');
IBM docs say it'll just work as UNC... but it doesn't... so at this point I'm not sure what to do.
Did you mount your winDoze network share on the 'nix file system? Just because winDoze is sharing the directory doesn't mean anybody else knows it's there - you still have to mount the directory for your PHP code to be able to see it.
BTW, this isn't a programming question, so it really doesn't belong here, you should be asking on ServerFault.
EDIT
Try this: Open a shell prompt on your IBM system, and run this command:
find / -name "<drive>"
where <drive> is the share name of the Windows network share. If find finds a location for your network share, you will have the path to use in its output.
If find returns an empty result set, run mount at the shell prompt. You will get an output that looks something like this:
/dev/vzfs on / type reiserfs (rw,usrquota,grpquota)
proc on /proc type proc (rw,relatime)
sysfs on /sys type sysfs (rw,relatime)
none on /dev type tmpfs (rw,relatime)
none on /dev/pts type devpts (rw,relatime)
none on /proc/sys/fs/binfmt_misc type binfmt_misc (rw,relatime)
Chances are extremely high that you won't find your network share <drive> in this list, either. That means you need to mount the network share as a resource on your Unix system. There should be an empty directory (usually /mnt) that you can mount the network share on, read the mount man page for instructions.

Bash sanitize_file_name function

I'm attempting to find a way to sanitize/filter file names in a Bash script the exact same way as the sanitize_file_name function from WordPress works. It has to take a filename string and spit out a clean version that is identical to that function.
You can see the function here.
GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu)
Ubuntu 14.04.5 LTS (GNU/Linux 3.13.0-57-generic x86_64)
This is perl 5, version 18, subversion 2 (v5.18.2) built for x86_64-linux-gnu-thread-multi
Example input file names
These can be and often are practically anything you can make a filename on any operating system, especially Mac and Windows.
This File + Name.mov
Some, Other - File & Name.mov
ANOTHER FILE 2 NAME vs2_.m4v
some & file-name Alpha.m4v
Some Strange & File ++ Name__.mp4
This is a - Weird -# Filename!.mp4
Example output file names
These are how the WordPress sanitize_file_name function makes the examples above.
This-File-Name.mov
Some-Other-File-Name.mov
ANOTHER-FILE-2-NAME-vs2_.m4v
some-file-name-Alpha.m4v
Some-Strange-File-Name__.mp4
This-is-a-Weird-#-Filename.mp4
It doesn't just have to solve these cases, it has perform the same functions that the sanitize_file_name function does or it will produce duplicate files and they won't be updated on the site.
Some thoughts I've had are maybe I can somehow use that function itself but this video encoding server doesn't have PHP on it since it's quite a tiny server and normally just encodes videos and uploads them. It doesn't have much memory, CPU power or disk space, it's a DigitalOcean 512MB RAM server. Maybe I can somehow create a remote PHP script on the web server to handle it through HTTP but again I'm not entirely sure how to do that either through Bash.
It's too complicated for my limited Bash skills so I'm wondering if anyone can help or knows where a script is that does this already. I couldn't find one. All I could find are scripts that change spaces or special characters into underscores or dashes. But this isn't all the sanitize_file_name function does.
In case you are curious, the filenames have to be compatible with this WordPress function because of the way this website is setup to handle videos. It allows people to upload videos through WordPress that are then sent to a separate video server for encoding and then sent to Amazon S3 and CloudFront for serving on the site. However it also allows adding videos through Dropbox using the External Media plugin (which actually is duplicating the video upload with the Dropbox sync now but that's another minor issue). This video server is also syncing to a Dropbox account and whitelisting the folders in it and has this Bash script watching a VideoServer Dropbox folder using inotifywait which copies videos from it to another folder temporarily where the video encoder encodes them. This way when they update the videos in their Dropbox it will automatically re-encode and update the video shown on the site. They could just upload the files through WordPress but they don't seem to want to or don't know how to do that for some reason.
If you have Perl installed, try with:
#!/bin/bash
function sanitize_file_name {
echo -n $1 | perl -pe 's/[\?\[\]\/\\=<>:;,''"&\$#*()|~`!{}%+]//g;' -pe 's/[\r\n\t -]+/-/g;'
}
filename="Wh00t? it's a -- re#lly-weird {file&name} (with + Plus and__1% #of# [\$qRots\$!]).mov"
cleaned=$(sanitize_file_name "$filename")
echo original : "$filename"
echo sanitised: "$cleaned"
Result is:
original : Wh00t? it's a -- re#lly-weird {file&name} (with + Plus and__1% #of# [$qRots$!]).mov
sanitised: Wh00t-it's-a-re#lly-weird-filename-with-Plus-and__1-of-qRots.mov
Looking at WP function, this emulates it quite well.
Inspired by the answer.
EscapeFilename()
{
printf '%s' "$#" | perl -pe 's/[:;,\?\[\]\/\\=<>''"&\$#*()|~`!{}%+]//g; s/[\s-]+/-/g;';
}

eSpeak to mp3 in php on both windows and linux (online text-to-speech)

I want to implement simple text-to-speech script in my web application that would dynamically generate mp3's out of given texts.
It needs to run in both:
my local WAMP server on windows
and my online linux server
eSpeak doesn't offer the highest quality in sound but at least a strong support in languages, simple implementation and also it's free. So after a little digging i realized there are not much examples of integrating it into php. I concluded StackOverflow should contain a simple implementation of a php text to speech script that generates mp3 with eSpeak and lame.
First we need to setup path to espeak and lame. Make sure you have installed both. In my case it looks like this:
I tought, someone might find this useful. I'm using this code to generate my command in local windows wamp server and online linux server:
// APPLICATION PATHS AND CONFIG
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
//This is a server using Windows!
define('ESPEAK', '..\application\libraries\espeak-win\command_line\espeak');
define('LAME', '..\application\libraries\espeak-win\command_line\lame');
}
else {
//This is a server not using Windows!
define('ESPEAK', '/usr/bin/espeak');
define('LAME', '/usr/bin/lame');
}
Then, write your own command to be executed. I used %s spots to be replaced later with desired values. List of espeak commands can be found here.
In case you don't need mp3 conversion and you are satisfied with .wav files, just remove the part after | (including this character) and replace argument --stdout with this two args -w desired_file_path. In that case make sure to correctly set %s variables later on.
define('COMMAND', ESPEAK.' --stdout -v %s+m3 -p 60 -a 75 -s 130 "%s" | '.LAME.' --preset voice -q 9 --vbr-new - %s');
and then execute the script like this:
$lang_voice = 'en';
$input_text = 'some input text to read';
$file_path = 'voice-cache/output.mp3'
$exe_path = sprintf(COMMAND, $lang_voice, $input_text, $file_path); // fills %s spots
exec($exe_path);
As a last step, just output generated file:
header('Content-Type: audio/mpeg');
header('Content-Length: '.filesize($file_path));
readfile($file_path);

Print to Zebra printer in php

Looking for the proper code to print from php web page to a zebra IP printer using RAW port 9100. Does anyone know if this is possible? I need to send a string in ZPL formatted output direct to ZM400 label printer. I've searched high and low, the closest I've found is this: Print directly to network printer using php
It seems very close to what I need, but when my php page hits that code, it doesn't do anything. Here's the code I used:
<?php
$handle = printer_open('\\\\192.168.2.206:9100\\');
printer_set_option($handle, PRINTER_MODE, "RAW");
printer_write($handle, "TEXT To print");
printer_close($handle);
?>
I realise this question is a little old but I recently had to perform this exact task and here is how I did it.
Main server is a Cloud-Based PHP server which is not on the local network. On the local network we have another machine which is simply running WAMP and this script, the Zebra printer itself is also on the local network at IP 192.168.1.201:
<?php
/*
* File Allows printing from web interface, simply connects to the Zebra Printer and then pumps data
* into it which gets printed out.
*/
$print_data = $_POST['zpl_data'];
// Open a telnet connection to the printer, then push all the data into it.
try
{
$fp=pfsockopen("192.168.1.201",9100);
fputs($fp,$print_data);
fclose($fp);
echo 'Successfully Printed';
}
catch (Exception $e)
{
echo 'Caught exception: ', $e->getMessage(), "\n";
}
Then, on the webpage generated by the cloud server we have some code which simply does an Ajax POST to the server on the local network, posting in the zpl_data to be printed.
Edit 2017
We've now moved things over to run through PrintNode (https://www.printnode.com/). We've found it to be really good so far, and allows us to print all kinds of documents without needing to use our own proxies, and also provide a whitelabelled installer so it looks like our own product. I'm not affiliated with PrintNode.
If you're looking to send ZPL to the printer, you don't necessarily need a dedicated printing library. You just need to open up a socket to that printer and send your ZPL directly. This is more of a general PHP socket-communication question as opposed to a printer-specific question.
If the server hosting your web app and the printers are on the same network, then you will be able to open the socket and send the ZPL. If, however, your printers and web app server are on different networks, you will not be able to print over sockets, on that model printer, without additional browser plugins or add-ons. Generally speaking, accessing a remote printer (or any device) via a web-site is a security risk.
The printer_open() and related functions are not part of the standard PHP language; they are part of an extension.
If you want to use them, you'll need to install the extension: See here for info on the printer extension.
However, please note that this extension is only available for PHP running on Windows.
If your server is not Windows, you will need to use an external program to send data to the printer. An example might look like this:
exec("lpr -P 'printer' -r 'filename.txt');
This info, and more can be found elsewhere on SO -- eg here: printing over network from PHP app
Hope that helps.
After hours of searchings I get the solutions :
After you install the printer on the needed IP:
exec('lp -d printer file');
In my case the command was:
exec('lp -d Epson-Cofetarie /home/clara/Desktop/txt.txt');
Where: printer = Epson-Cofetarie
file = /home/clara/Desktop/txt.txt
file need Apsolute path
I hope, this simple code will resolve the problem,
Put your ZPL code in a file e.g "barcode.zpl"
Share your Zebra Printer, so that it can be accessed In Windows Explorer by typing
e.g "\192.168.1.113[YOUR PRINTER NAME]";
Create PHP File, and write code:
<?php
$file="barcode.zpl";
copy($file, "//192.168.1.113/ZDesigner GK420t");
?>
Thank You

Print directly to network printer using php

I am unable to print a page to a network printrer using php.
But this works if it is a local printer.
I have installed php_printer.dll and enabled in php.ini
The following is the code:
//$handle = printer_open("Send To OneNote 2007"); ///This Works
$handle = printer_open('\\\\192.168.0.8\\Canon MF4320-4350');
printer_set_option($handle, PRINTER_MODE, "RAW");
printer_write($handle, "TEXT To print");
printer_close($handle);
It shows the error
Warning: printer_write() [function.printer-write]: couldn't allocate the
printerjob [5] in E:\Server\xampp\htdocs\Kiosk\Admin\print.php on line 16
If you used the command line PHP (CLI) the printing to network printers would work. Your $addr is correct by the way.
The issue lies with PHP when you combine it with Apache. In windows, your php scripts would run under the user SYSTEM. Because of security concerns, all network resources are not visible to SYSTEM.
To resolve this problem, create a new user with admin privileges (or at least with Network Resource visibility). In Windows, if you run Apache as a service, click on the SERVICE button in the Apache Service Monitor. Under Apache 2.2, right click on properties. Under the LOGIN tab, change the user from SYSTEM to your newly created user account. Restart Apache. You should be able to run your PHP script to print to network printers now.
Try using either "s with 4\ or 's with 3. eg:
$handle = printer_open("\\\\192.168.0.8\\Canon MF4320-4350");
// or
$handle = printer_open('\\\192.168.0.8\Canon MF4320-4350');
Also, try using a domain name rather than IP (eg. computer-name or full.address.example.com).
Just looking at that string, it feels very much as if it's likely to be caused by back-slash escaping going wrong.
Debugging tip: Set your network address in a variable rather than directly in printer_open(). Then use print() or similar to display the value.
<?php
$addr = '\\\\192.168.0.8\\Canon MF4320-4350';
print $addr;
printer_open($addr);
...
?>
This will allow you to see the value of the string that you're using, which might help you see what's going wrong, and more importantly, help you see how to fix it.
Hope that helps.

Categories