HTML通过Websocket发送页面内容给打印客户端

HTML通过Websocket发送页面内容给打印客户端

1、概述

 需求如下: 网页将当前html内容通过ws发送给客户端程序,调用本地打印机打印网页内容。

2、客户端程序

  1. demo 实现ws的服务端
    结构如下:
    在这里插入图片描述
    代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Windows.Forms;

namespace Fleck.Samples.ConsoleApp
{
    class Server
    {
        static void Main()
        {
            
            FleckLog.Level = LogLevel.Debug;
            var allSockets = new List<IWebSocketConnection>();
            var server = new WebSocketServer("ws://0.0.0.0:8181");
            server.Start(socket =>
                {
                    socket.OnOpen = () =>
                        {
                            Console.WriteLine("Open!");
                            allSockets.Add(socket);
                        };
                    socket.OnClose = () =>
                        {
                            Console.WriteLine("Close!");
                            allSockets.Remove(socket);
                        };
                    socket.OnMessage = message =>
                        {
                            Console.WriteLine("123");
                            Console.WriteLine(message);
                           
                            allSockets.ToList().ForEach(s => s.Send("Echo: " + message));
                        };
                });


            var input = Console.ReadLine();
            while (input != "exit")
            {
                foreach (var socket in allSockets.ToList())
                {
                    socket.Send(input);
                }
                input = Console.ReadLine();
            }

        }
    }
}

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
    <title>websocket client</title>
    <script type="text/javascript">
        var start = function () {
            var inc = document.getElementById('incomming');
            var wsImpl = window.WebSocket || window.MozWebSocket;
            var form = document.getElementById('sendForm');
            var input = document.getElementById('sendText');
            
            inc.innerHTML += "开始连接ws服务 .....<br/>";

            // create a new websocket and connect
            window.ws = new wsImpl('ws://localhost:8181/');

            // when data is comming from the server, this metod is called
            ws.onmessage = function (evt) {
                inc.innerHTML += evt.data + '<br/>';
            };

            // when the connection is established, this method is called
            ws.onopen = function () {
                inc.innerHTML += '服务已连接<br/>';
            };

            // when the connection is closed, this method is called
            ws.onclose = function () {
                inc.innerHTML += '连接关闭<br/>';
            }
            
			form.addEventListener('submit', function(e){
				e.preventDefault();
				var val = input.value;
				ws.send(val);
				input.value = "";
			});
            
        }
        window.onload = start;
    </script>
</head>
<body>
	<form id="sendForm">
		<input id="sendText" placeholder="Text to send" />
	</form>
    <pre id="incomming"></pre>
</body>
</html>

  1. 客户端集成打印和ws服务

    结构如下:
    在这里插入图片描述
    界面如下:
    在这里插入图片描述
    代码如下:
    PrintMain.cs

using Fleck;
using System;
using System.IO;
using System.Text;
using System.Windows.Forms;

namespace Print
{
    public partial class PrintMain : Form
    {
        public PrintMain()
        {
            InitializeComponent();
            this.WindowState = FormWindowState.Maximized;
            var server = new WebSocketServer("ws://0.0.0.0:8181");
            server.Start(socket =>
            {
                Socket = (WebSocketConnection)socket;
                socket.OnOpen = () =>
                {
                    Console.WriteLine("Open!");

                };
                socket.OnClose = () =>
                {
                    Console.WriteLine("Close!");

                };
                socket.OnMessage = message =>
                {
                    Console.WriteLine(message);
                    GetHtmlTemplate(message);
                    this.webBrowser.Url = new Uri(Application.StartupPath.ToString() + "\\" + "Demo.html");
                };
            });
            this.webBrowser.Url = new Uri(Application.StartupPath.ToString() + "\\" + "Demo.html");
            //当加载文件完成后激发手动追加的事件
            this.webBrowser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(PrintDocument);
            this.webBrowser.Focus();
        }
        public WebBrowser PrintObject { get; set; }
        public IWebSocketConnection Socket { get; set; }

        private void PrintSet_Click(object sender, EventArgs e)
        {
            if (PrintObject != null)
            {
                PrintObject.ShowPrintDialog();
            }
            else
            {
                MessageBox.Show("无内容可打印!");
            }
        }

        private void PageSet_Click(object sender, EventArgs e)
        {
            //弹出页面设置对话框-----即上方定义的新进程需要处理的窗口
            if (PrintObject != null)
            {
                PrintObject.ShowPageSetupDialog();
            }
            else
            {
                MessageBox.Show("无内容可打印!");
            }
        }

        private void PrintView_Click(object sender, EventArgs e)
        {
            if (PrintObject != null && !PrintObject.DocumentText.Contains("&template&"))
            {
                PrintObject.ShowPrintPreviewDialog();
            }
            else
            {
                MessageBox.Show("无内容可预览!");
            }
        }

        private void btnPrint_Click(object sender, EventArgs e)
        {
            if (PrintObject != null && !PrintObject.DocumentText.Contains("&template&"))
            {
                PrintObject.Print();
                PrintObject.Dispose();
            }
            else
            {
                MessageBox.Show("无内容可打印!");
            }
        }

        private void PrintDocument(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            PrintObject = ((WebBrowser)sender);
            if (PrintObject != null && !PrintObject.DocumentText.Contains("&template&"))
            {
                PrintObject.Print();
            }
        }

        private void btnPrintProp_Click(object sender, EventArgs e)
        {
            if (PrintObject != null)
            {
                PrintObject.ShowPropertiesDialog();
                //MessageBox.Show(AppDomain.CurrentDomain.BaseDirectory);
            }
            else
            {
                MessageBox.Show("无内容可打印!");
            }
        }
        //读取模板并替换传输过来的html内容
        private void GetHtmlTemplate(string message)
        {
            Stream myStream = new FileStream(Application.StartupPath.ToString() + "\\" + "Demo.html", FileMode.Open);
            Encoding encode = System.Text.Encoding.GetEncoding("utf-8");
            StreamReader myStreamReader = new StreamReader(myStream, encode);
            string strhtml = myStreamReader.ReadToEnd();
            string stroutput = strhtml.Replace("&template&", message);
            myStream.Seek(0, SeekOrigin.Begin);
            myStream.SetLength(0);
            StreamWriter sw = new StreamWriter(myStream, encode);
            sw.Write(stroutput);
            sw.Flush();
            sw.Close();
            myStream.Close();

        }

        private void btnSendMsgToClient_Click(object sender, EventArgs e)
        {
            if (Socket != null)
            {

                Socket.Send("服务端发送的消息:" + this.txtServerMsg.Text + "\r\n");
                this.txtServerMsg.Text = "";
            }
        }
 
    }
}

Demo.html

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">

<head>
    <meta charset="utf-8" />
    <title></title>
</head>

<body>

    &template&

</body>

</html>

3、Html发送内容

   handlePrint() {
      if (this.isReport) {
        //打印
        var dom = document.getElementsByClassName('ppxpxpxpxppxpx')
        console.log('打印', this.readScaleSize(dom))
        let oldScaleSize = this.readScaleSize(dom)
        this.scaleToSize(1, dom)
        // ****************连接websocket 打印服务 strat****************
        console.log('dom: ', dom)
        let checkboxs = dom[0].getElementsByClassName('ant-checkbox ant-checkbox-checked')
        if (checkboxs && checkboxs.length > 0) {
          for (let index = 0; index < checkboxs.length; index++) {
            const element = checkboxs[index]
            let checkbox = element.children[0]
            checkbox.setAttribute('checked', 'checked')
          }
        }
        var arr = Array.prototype.slice.call(dom)
        console.log('arr: ', arr)
        this.websocket = new WebSocket('ws://localhost:8181/')
        this.handleWebsocket(arr[0].innerHTML)
        // ****************连接websocket 打印服务 end****************
        $(dom).printThis({
          debug: false, // show the iframe for debugging
          importCSS: true, // import parent page css
          importStyle: true, // import style tags
          printContainer: true, // print outer container/$.selector
          loadCSS: '', // path to additional css file - use an array [] for multiple
          pageTitle: '', // add title to print page
          removeInline: false, // remove inline styles from print elements
          removeInlineSelector: '*', // custom selectors to filter inline styles. removeInline must be true
          printDelay: 333, // variable print delay
          header: null, // prefix to html
          footer: null, // postfix to html
          base: true, // preserve the BASE tag or accept a string for the URL
          formValues: true, // preserve input/form values
          canvas: true, // copy canvas content
          doctypeString: '', // enter a different doctype for older markup
          removeScripts: false, // remove script tags from print content
          copyTagClasses: true, // copy classes from the html & body tag
          beforePrintEvent: () => {
            this.scaleToSize(oldScaleSize, dom)
          }, // function for printEvent in iframe
          beforePrint: null, // function called before iframe is filled
          afterPrint: null // function called before iframe is removed
        })
      }
    },

4、总结

  1. 前端我们用的AntDesign+vue,传递Checkbox、Radio这些组件的时候,做了特殊处理,转为原生的选中效果。
    let checkboxs = dom[0].getElementsByClassName('ant-checkbox ant-checkbox-checked')
        if (checkboxs && checkboxs.length > 0) {
          for (let index = 0; index < checkboxs.length; index++) {
            const element = checkboxs[index]
            let checkbox = element.children[0]
            checkbox.setAttribute('checked', 'checked')
          }
        }
  1. 网页端我们也支持浏览器自身的打印,用的是printThis库,遇到的问题也是关于Checkbox,选中效果无法呈现,源代码加了这句代码 -webkit-print-color-adjust: exact;
 let  bodyStyle = '<style type="text/css">body {height: auto !important;-webkit-print-color-adjust: exact;}</style>'
 $head.append(bodyStyle)
  1. 关于ws的心跳机制,因为项目要做剔下线的功能,不允许二次登录。
    处理方式:数据接收,保持与后端的通信, 约定:前端 ping 后端 pong
    前端发送一个心跳ping,后端收到后,返回一个心跳消息 pong,重新连接ws。
  2. 客户端的打印主要用的是webBrowser集成网页打印,通过占位符替换网页内容。
  3. 客户端websocket使用 Fleck第三方库。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值