将 PHP 打印到网络打印机

20

我要做什么

在网络打印机上打印PDF文档,同时传递打印参数,例如颜色、方向、双面等。

更多信息

  • 我们有多个网络打印机,其IP地址是静态且已知的(例如192.168.0.10)。
  • 我找到了一份文档,其中包含可以传递给打印机以更改打印设置参数/选项列表这里(其中大部分可以在第25页找到)。
  • 我们正在创建一个过程,通过该过程将以黑白方式打印文档,除第二页外。这意味着第一页第三页及之后的页面都将以黑白方式打印第二页将以彩色方式打印。(这是由于彩色打印的成本,加上我们的其他页面不包含颜色,因此将它们打印成彩色极其无意义且大约要昂贵8倍-该过程每月将打印数千页,这会增加很多$$$)

我已经在某些方面取得了一定的成功

我登录了其中一台打印机(192.168.0.10 - 理光 MP C5503 [如果你真的想知道]),并添加了FTP访问权限。

使用Windows命令提示符打印文档是可行的!

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

我尝试过的事情

尝试1:使用PHP的exec()函数

我已经尝试了很多种方法来使exec工作,但都没有成功。我无法使用PHP的exec函数运行多行命令(理想情况下,运行以下命令)。在exec()内运行以下内容时,我无法连接到FTP,因为每行必须在前一行运行后才能执行。我在网上找不到任何东西(多次Google搜索没有结果[除了如何从cmd中回显多个输出行 - 而不是如何连续插入多个cmd行])

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

尝试2:使用PHP的exec()函数

我尝试通过传递一个文本文件来运行ftp命令,正如this帖子中的一些答案所建议的那样。但是这种解决方案并没有像预期的那样工作。在命令提示符中运行ftp -i -s:test.txt可以成功,但在PHP中却不行。

PHP文件:

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

文本文件 (test.txt)

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

尝试3:使用PHP的FTP函数
现在我无法弄清如何通过ftp将文件发送到打印机并设置打印机设置。
$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';
}

理想情况下...

我正在寻找一种适用于Windows和Linux系统的解决方案,因为我们也正在从IIS迁移到NGINX(谢天谢地...)。我认为最好的实现方法是在Windows上使用ftp,在Linux上使用rcprsh(因为我在更多信息中附加的打印机文档在我试图做什么部分提到了这些打印方法)。

我希望我们不必生成txt文件或其他文件类型来打印这些文档。我们的用户可能一次处理数百个文件,我知道我们可以为每个txt文件命名,然后在脚本成功运行后将其删除,但我更喜欢一种干净的解决方案,可以传递参数,例如打印机(从gethostbyaddr()函数获取的IP或名称),用户名,密码,要打印的文件,选项(即颜色、双面、文件类型、方向、装订等)。我们正在使用MPDF生成我们的PDF文件,因此最好使用一种方法将文件放置在没有实际创建它的服务器上,我们随后必须删除它(即用于电子邮件的MPDF字符串附件),但这些不是必需的。
此外,解决方案必须与PHP兼容。
在发布此帖子后,我将继续调查在网络打印机上打印文档的更多方法,直到找到一个可行的解决方案,并根据每次尝试更新我的帖子。
非常感谢任何关于此事的帮助。

编辑


不成功的方法

方法:PHP打印函数

打印函数确实允许打印,但是它们不允许控制打印作业(例如颜色/黑白打印、文件类型、双面打印等选项)。因此,这些选项(除非有人有“黑科技”)将无法使用。

方法:JavaScript/AJAX

虽然JavaScript/AJAX可以用于打印(并允许打印设置),但我们可能会一次处理数百页,并且处理可能会将打印作业推送到多台打印机(即在不同的办公室)。我们的想法是自动化我们的打印流程以及未来的流程。


未经测试的方法

方法:尚未测试


解决方案?

最终,我创建了一个C#脚本来完成我需要做的一切。由于我的打印设置要求相当具体,这是微软的System.Drawing.Printing名称空间的链接。使用此名称空间,我能够为自己的需求创建适当的方法。下面是一些StackOverflow问题/答案,提供更多关于用法的细节:

如何在PHP中运行C#?那取决于你。您可以与C# API进行接口交互(例如在另一台Web服务器上运行C#),引用.NET DLL,使用PeachPie或在运行时注入声明。


您也可以使用PowerShell来创造一些东西(请参见PrintManagement文档)。这将允许您使用exec()运行脚本 - 有关从PHP执行PowerShell的问题,请参见此问题(execution of PowerShell from PHP)


你是否考虑过使用IPP而不是FTP与打印机通信? - Dezza
@Dezza 我还没有查看过。我现在会进行调查。谢谢。 - ctwheels
你尝试使用 printer_open ([ string $printername ] ) PHP 函数了吗? - odedta
1
@odedta 可能是有可能的,但是如果有人决定处理大约300个文件,可能需要几分钟才能生成。如果他们离开页面,它就会停止运行。这也意味着他们必须选择打印机。我们有多个办公室,我们的员工可能会为另一个办公室处理文档(这意味着应该在那里打印)。我们正在寻求自动化流程并防止用户错误。 - ctwheels
1
谢谢你提醒我一个 SO 问题应该是什么样子的,以及还有希望! - DaGhostman Dimitrov
显示剩余3条评论
3个回答

3

试试这个:

$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';
    }
}

请告诉我你得到了什么。

更新:打印机手册第19页可知,您可以使用以下命令同时发送文件并设置设备选项:

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

在这个例子中,file1 是你要发送的本地文件名,filetype=postscript,tray=tray1,copies=3,resolution=600 是远程文件名。 要精确的说,实际的FTP命令是:
STOR filetype=postscript,tray=tray1,copies=3,resolution=600

使用PHP的FTP函数,PHP代码如下:
ftp_put($ftp,'filetype=postscript,tray=tray1,copies=3,resolution=600','file1',FTP_BINARY);

$ftp是从成功调用ftp_connect()后的连接句柄。

将其应用于我的第一个示例,代码变为:

$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';
    }
}

试一试吧。


虽然使用PHP的ftp函数可能可以通过ftp上传文件到打印机,但是在这样做时无法指定打印机设置。ftp_put函数不允许使用参数(除非另一个ftp_*函数允许)。此外,我认为您提供的代码不会正确工作,因为根据文档,ftp_put的第二个参数必须是远程文件(即myfile.pdf):http://php.net/manual/en/function.ftp-put.php - ctwheels
根据您提供的手册链接,它将会。请给我几分钟时间更新我的答案。 - Rei
我已经点赞了这个答案,因为这段代码允许网络打印并指定与整个打印作业相关联的属性,其他人可能会发现有用,但是我们仍然无法处理1个打印作业并为单个页面指定颜色/黑白设置。一个选项是创建3个打印作业,其中第一个和第三个是黑白的,第二个是彩色的,但是这将作为3个单独的打印作业进行,这不允许完成(如装订),还有其他打印作业在3个打印作业之间进行的可能性。 - ctwheels
@ctwheels 为了保持每个文档只有1个打印作业,您尝试过将PDF文档渲染为黑色,除了第2页,并配置打印机自动检测仅黑色页面吗?我配置了我的打印机来执行此操作,我节省了很多CMY色调。您的打印机似乎比我的先进得多,所以我想它应该能够做到同样的事情。也许可以向Ricoh支持寻求类似的配置。 - Rei

0
我找到了一种适用于某些打印机的方法。 我使用fpdf创建一个pdf文件,然后直接发送到打印机:
//This is the final output from fpdf
$pdf -> Output('tmp/lbl.pdf', 'F');

if (($conp = fsockopen("10.0.0.100", 9100, $errno, $errstr)) === false)
    echo 'Connection Failed' . $errno . $errstr;
else {
    fputs($conp, file_get_contents('tmp/lbl.pdf'));
    fclose($conp);
}

这个程序可以在Xerox上运行,但是在Sharp上不行。我发现fpdf是在1.4版本上创建的,有些打印机不支持。 因此,我将其作为tiff格式发送,并使用ghostscript转换pdf。

这段代码在安装了apache(WAMP)的Windows 10 x64上使用gs x32:

    shell_exec("\"c:\\program files (x86)\\gs\\gs9.56.1\\bin\\gswin32c\" -sDEVICE=tiffg4 -dNOPAUSE -dQUIET -dBATCH -sOutputFile=tmp\\lbl.tiff tmp\\lbl.pdf");
    fputs($conp, file_get_contents('tmp/lbl.tiff'));

在安装了IIS的Windows Server 2019 x64上,我需要切换到gs 64并仅更改下一行代码:
shell_exec("\"c:\\program files\\gs\\gs9.56.1\\bin\\gswin64c\" -q -dNOPAUSE -sDEVICE=tiffg4 -sOutputFile=tmp\\lbl.tiff tmp\\lbl.pdf -c quit");

我必须在两个地方使用完整的gs路由才能使其正常工作。


-1

虽然我尝试了很多次,但无法在网络打印机上打印,并且找不到合适的解决方案。同时,shell_exec("AcroRd32.exe")和通过"其他pdf打印机"也无法工作,因为我的WAMP服务器需要GUI程序的特殊权限。现在我终于找到了适合我的解决方案。

这是仅适用于Windows的解决方案

下载PDFtoPrinter

用于打印网络/本地打印机的代码

$command = escapeshellcmd('PDFtoPrinter YOURFILE.PDF "\\\YOURSERVERNAME\YOURPRINTERNAME"');
$output = shell_exec($command);
echo $output;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接