Web实现静默打印
|
admin
2025年12月9日 11:30
本文热度 6
|
网页端由于安全限制,禁止直接访问客户端设备,要实现静默打印,可以有以下几种办法。1、封装webview2,运行web页面,可实现调用本地打印机。2、客户端运行守护程序,js通过websocket与守护程序通信,由守护程序打印。3、通过云打印。本文主要使用websocket与客户端守护程序的方式来实现。1、客户端守护程序:通过HttpListener监听用户请求,并打印。客户端设置打印机,纸张格式。private const int Port = 8777;private HttpListener _listener;private readonly string _printerConfigFile;private readonly Control _parent;private CancellationTokenSource _cancellationTokenSource; public async Task Start() { LoadSettings();
_listener = new HttpListener(); _listener.Prefixes.Add($"http://localhost:{Port}/"); _listener.Start();
Console.WriteLine($"🛡️ WebSocket服务已启动: ws://localhost:{Port}/print");
try { while (!_cancellationTokenSource.Token.IsCancellationRequested) { var context = await _listener.GetContextAsync(); if (context.Request.IsWebSocketRequest) { await ProcessWebSocketRequest(context); } else { context.Response.StatusCode = 400; context.Response.Close(); } } } catch (Exception ex) { Console.WriteLine($"🔴 服务异常: {ex.Message}"); } }
并打印 private async Task ProcessWebSocketRequest(HttpListenerContext context) { WebSocket webSocket = null; try { var wsContext = await context.AcceptWebSocketAsync(null); webSocket = wsContext.WebSocket; Console.WriteLine("🟢 客户端已连接");
var buffer = new byte[1024 * 1024]; while (webSocket.State == WebSocketState.Open && !_cancellationTokenSource.Token.IsCancellationRequested) { WebSocketReceiveResult result; string json = string.Empty; using (var ms = new MemoryStream()) { do { var segment = new ArraySegment<byte>(buffer); result = await webSocket.ReceiveAsync(segment, CancellationToken.None); if (result.MessageType == WebSocketMessageType.Close) { await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "客户端关闭连接", CancellationToken.None); return; }
if (result.Count > 0) { ms.Write(buffer, 0, result.Count); } } while (!result.EndOfMessage); json = Encoding.UTF8.GetString(ms.ToArray()); } if (!string.IsNullOrEmpty(json)) { var printReq = new PrintRequest(); var obj = JObject.Parse(json); var jsonData = JsonConvert.DeserializeAnonymousType(json, new { ReportId = "", ReportContent = "", PrintCopies = 1 }); if (!string.IsNullOrEmpty(jsonData.ReportId) && !string.IsNullOrEmpty(jsonData.ReportContent)) { printReq.ReportId = jsonData.ReportId; printReq.ReportContent = Base64UrlEncoder.Decode(jsonData.ReportContent); printReq.PrintCopies = jsonData.PrintCopies; _parent.Invoke((MethodInvoker)delegate { PrintDocument(printReq); }); var response = JsonConvert.SerializeObject(new { Flag = true, Msg = "打印成功" });
await webSocket.SendAsync(new ArraySegment<byte>(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(response))), WebSocketMessageType.Text, true, CancellationToken.None); } } } } catch (WebException ex) { Console.WriteLine($"🔴 WebSocket错误: {ex.Message}"); } catch(Exception ex) { var response = JsonConvert.SerializeObject(new { Flag = false, Msg = ex.Message }); await webSocket.SendAsync(new ArraySegment<byte>(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(response))), WebSocketMessageType.Text, true, CancellationToken.None); } finally { webSocket?.Dispose(); Console.WriteLine("🔴 客户端已断开"); } }
2、web端js,通过websocket访问ws://localhost与守护程序交互。注:如果web端使用了https,一定要用ws,用http会被浏览器阻止。 async printManual(){ if(this.isPrinting){ this.$message.info('请等待当前打印完成'); return } if(!this.printData.BoxQty) { this.$message.info("每箱数量必须大于0"); return; } if(!this.printData.GrossWeight) { this.$message.info("毛重必须大于0"); return; } this.isPrinting=true; this.setPrintResult('printing', '正在发送打印任务...'); try{ const res=await this.$post("@Url.Action("PrintManual", "Print")",this.printData); if(res.data.Status!=='OK'){ throw new Error(res.data.Msg||'获取打印数据失败'); } const taskId=Date.now().toString(); this.setPrintResult('printing', '正在连接打印机...', { taskId: taskId }); if(!this.printManager.isConnected){ await this.printManager.connect(); }
await this.printManager.send(JSON.stringify(res.data.Response)); this.setPrintResult('printing', '已发送到打印机,等待响应...'); this.printTimeoutTimer = setTimeout(() => { if (this.isPrinting) { this.handlePrintTimeout(); } }, 30000); }catch(err){ this.handlePrintError(error.message); }
* 连接 WebSocket 服务器 */ async connect() { if (this.isConnected || this.isConnecting) { this.log('⏳ 已连接或正在连接中'); return this.waitForConnection(); }
this.isConnecting = true; this.log('🔌 开始连接 WebSocket...');
return new Promise((resolve, reject) => { try { this.ws = new WebSocket(this.config.url); this.ws.binaryType = this.config.binaryType;
const connectionTimeout = setTimeout(() => { if (!this.isConnected) { this.log('❌ 连接超时'); this.ws.close(); reject(new Error('连接超时')); this.isConnecting = false; } }, this.config.connectionTimeout);
this.ws.onopen = () => { clearTimeout(connectionTimeout); this.log('✅ WebSocket 连接成功'); this.isConnected = true; this.isConnecting = false; this.reconnectAttempts = 0;
this.triggerEvent('open', null); this.triggerEvent('connected', null);
this.startHeartbeat();
this.flushMessageQueue();
resolve(); };
this.ws.onclose = (event) => { clearTimeout(connectionTimeout); this.log(`🔴 连接关闭,代码: ${event.code}, 原因: ${event.reason}`); this.isConnected = false; this.isConnecting = false;
this.stopHeartbeat();
this.triggerEvent('close', event); this.triggerEvent('disconnected', event);
if (this.config.reconnect && event.code !== 1000) { this.reconnect(); } };
this.ws.onerror = (error) => { clearTimeout(connectionTimeout); this.log('❌ WebSocket 错误:', error); this.isConnecting = false;
this.triggerEvent('error', error);
reject(error); };
this.ws.onmessage = (event) => { this.handleMessage(event); };
} catch (error) { this.isConnecting = false; this.log('❌ 创建 WebSocket 失败:', error); reject(error); } }); }
阅读原文:https://mp.weixin.qq.com/s/I7rw7h4bPNAY1lVdS05FPQ
该文章在 2025/12/9 11:30:07 编辑过