基于CodeIgniter/PHP实现跨网络IP打印机打印任务的技术求助
跨公网PHP+CodeIgniter打印到指定IP打印机解决方案
核心前提确认
- 目标打印机必须拥有公网可访问的IP地址,且默认打印端口
9100已在路由器/防火墙处完成端口映射,确保公网能连通该端口 - 若打印机仅处于局域网内,必须在其所在网络部署中转代理,否则公网服务无法直接访问
优化版Socket打印方案(适配CodeIgniter)
之前的Socket代码存在未处理二进制打印数据、错误捕获不完善的问题,以下是封装成CodeIgniter库的优化版本:
1. 创建CodeIgniter打印库(application/libraries/Printer.php)
<?php defined('BASEPATH') OR exit('No direct script access allowed'); class Printer { private $socket; private $printer_ip; private $port = 9100; public function __construct($printer_ip) { $this->printer_ip = $printer_ip; $this->create_socket(); } private function create_socket() { $this->socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); if (!$this->socket) { throw new Exception("Socket创建失败: " . socket_strerror(socket_last_error())); } } public function print_data($print_content) { $connection = socket_connect($this->socket, $this->printer_ip, $this->port); if (!$connection) { throw new Exception("连接打印机失败: " . socket_strerror(socket_last_error($this->socket))); } $bytes_written = socket_write($this->socket, $print_content, strlen($print_content)); if ($bytes_written === false) { throw new Exception("发送数据失败: " . socket_strerror(socket_last_error($this->socket))); } usleep(500000); $this->close_socket(); return true; } private function close_socket() { if ($this->socket) { socket_close($this->socket); } } public function print_file($file_path) { if (!file_exists($file_path)) { throw new Exception("文件不存在"); } $file_content = file_get_contents($file_path); return $this->print_data($file_content); } }
2. 在控制器中调用
<?php defined('BASEPATH') OR exit('No direct script access allowed'); class Print_controller extends CI_Controller { public function index() { $this->load->library('printer', array('printer_ip' => 'xxx.xxx.xxx.xxx')); // 替换为打印机公网IP try { // 示例:热敏打印机ESC/POS指令 $print_content = "\x1B\x40"; // 初始化打印机 $print_content .= "测试打印内容\n"; $print_content .= "\x1B\x64\x02"; // 走纸2行 $print_content .= "\x1D\x56\x41\x00"; // 切纸 $this->printer->print_data($print_content); echo "打印任务提交成功"; } catch (Exception $e) { echo "错误: " . $e->getMessage(); } } }
基于IPP协议的打印方案
若打印机支持Internet Printing Protocol(IPP),可使用PHP的IPP客户端实现,无需直接操作Socket:
1. 安装IPP客户端库(Composer)
在CodeIgniter项目根目录执行:
composer require xerias/ipp
2. 控制器调用示例
<?php defined('BASEPATH') OR exit('No direct script access allowed'); require_once APPPATH . '../vendor/autoload.php'; class Ipp_print extends CI_Controller { public function index() { $printer_ip = 'xxx.xxx.xxx.xxx'; $ipp_client = new \Xerias\Ipp\IppClient($printer_ip, 631); // IPP默认端口631 $job = new \Xerias\Ipp\Job(); $job->setJobName('PHP打印任务'); $job->addDocument(file_get_contents('path/to/your/file.pdf'), 'application/pdf'); try { $response = $ipp_client->printJob($job); if ($response->getStatusCode() == 0x0000) { echo "打印任务提交成功"; } else { echo "提交失败: " . $response->getStatusMessage(); } } catch (\Exception $e) { echo "错误: " . $e->getMessage(); } } }
中转代理方案(打印机无公网IP时)
若打印机仅在局域网内,需在其所在网络部署中转服务:
1. 局域网内部署PHP中转脚本
<?php // proxy_printer.php $printer_ip = '192.168.1.100'; // 局域网内打印机IP $port = 9100; $print_content = file_get_contents('php://input'); $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); $result = socket_connect($socket, $printer_ip, $port); if ($result) { socket_write($socket, $print_content, strlen($print_content)); socket_close($socket); echo "转发成功"; } else { echo "转发失败"; }
2. 公网CodeIgniter端调用中转脚本
<?php defined('BASEPATH') OR exit('No direct script access allowed'); class Proxy_print extends CI_Controller { public function index() { $proxy_url = 'http://xxx.xxx.xxx.xxx/proxy_printer.php'; // 中转脚本公网地址 $print_content = "测试打印内容"; $this->load->library('curl'); $response = $this->curl->simple_post($proxy_url, $print_content, array('Content-Type: application/octet-stream')); echo $response; } }
关键注意事项
- 打印内容必须匹配打印机支持的格式:热敏打印机用ESC/POS指令,激光打印机用PCL/PS/PDF格式
- Socket方案需确保服务器PHP已启用
sockets扩展(在php.ini中开启extension=sockets) - 公网访问打印机时,需限制访问IP或使用VPN/加密传输,避免安全风险
内容的提问来源于stack exchange,提问作者oelimoe
相关产品推荐
相关产品推荐

