基於HTTP可供瀏覽器調用的本地打印程序


之前給公司做打印都是用ActiveX控件,只支持IE瀏覽器,最近需要支持谷歌,又不想去學谷歌插件編寫,於是就用本地啟動一個http服務器來供瀏覽器調用(寫成windows服務更好),同事用了都說好(笑)!為了方便大家使用,重新簡單的封裝了一下,源碼下載:點我下載

源碼簡單的封裝了一個webserver(基於httplistener,可以使用Nancy框架代替),可以大致了解HTTP服務器處理的流程:APACHE,NINGX等服務器主要負責響應瀏覽器HTTP(基於SOCKET)的請求,並將請求轉交給JAVA,C#,PHP等語言處理(應該就是啟動了一個該語言的虛擬機解析執行對應的代碼),再將處理結果返回給瀏覽器

 1 namespace LocalPrint.Web
 2 {
 3     //本地微型HTTP服務器,可以理解網絡請求處理的服務器處理流程
 4     class WebServer
 5     {
 6         HttpListener httpListener;
 7         public string Err;
 8         Dictionary<string, IHttpHandler> handlerMap = new Dictionary<string, IHttpHandler>();
 9         //啟動本地HTTP服務器,相當於APACHE,NGINX之類的WEB服務器,接受瀏覽器發送過來的SOCKET請求
10         public bool RunWeb(string url)
11         {
12             try
13             {
14                 httpListener = new HttpListener();
15                 httpListener.Prefixes.Add(url);
16                 httpListener.Start();
17                 var th = new Thread(Process);
18                 th.IsBackground = true;
19                 th.Start();
20                 return true;
21             }
22             catch (Exception ex)
23             {
24                 Err = "啟動本地服務器出現問題:" + ex.Message;
25                 return false;
26             }
27         }
28         //設置相應路由和相應的處理類
29         public bool AddHandler(string url,IHttpHandler httpHandler)
30         {
31             try
32             {
33                 handlerMap.Add(url, httpHandler);
34                 return true;
35             }
36             catch (Exception ex)
37             {
38                 Err = "添加路徑出錯:" + ex.Message;
39                 return false;
40             }
41         }
42         //HTTP數據處理,這一部分相當於C#,JAVA和PHP和其他語言的功能,WEB服務器將請求轉發給相應的語言處理,並把結果返回給瀏覽器
43         void Process()
44         {
45             for (; ; )
46             {
47                 var cnx = httpListener.GetContext();//獲取瀏覽器請求上下文,串行處理,也可以改成並行
48                 var req = cnx.Request;
49                 var rep = cnx.Response;
50                 rep.ContentEncoding = Encoding.UTF8;
51                 rep.Headers.Add("Access-Control-Allow-Origin", "*");//允許瀏覽器跨域!非常重要
52                 rep.StatusCode = 404;
53                 var ret = "pag not found";
54                 //rep.ContentType = "text";//返回內容,這里為text,ajax里面的請求datatype也需要設置為text或者html,不然會為null
55                 //這一部分其實就是大部分MVC網絡框架里的路由部分!這里簡單的發送原始文本給handler處理
56                 foreach (var kv in handlerMap)
57                 {
58                     if(System.Text.RegularExpressions.Regex.IsMatch(req.RawUrl,kv.Key))//正則匹配
59                     {
60                         var data = "";
61                         if (req.HttpMethod == "GET")
62                             data = req.RawUrl;//不做任何處理,直接將原始的http請求轉發到handler。。。
63                         else
64                         using (var r = new StreamReader(req.InputStream, Encoding.UTF8))
65                         {
66                             data = r.ReadToEnd();
67                         }
68                         ret = kv.Value.Handler(data);
69                         rep.StatusCode = 200;//ok
70                         break;
71                     }
72                 }
73                 //返回處理結果給瀏覽器
74                 using (var w = new StreamWriter(rep.OutputStream, Encoding.UTF8))
75                 {
76                     w.WriteLine(ret);
77                 }
78             }
79         }
80 
81     }
82 }
 1         void Process()
 2         {
 3             for(; ; )
 4             {
 5                 var cnx = httpListener.GetContext();
 6                 var req = cnx.Request;
 7                 var rep = cnx.Response;
 8                 rep.Headers.Add("Access-Control-Allow-Origin", "*");
 9                 var txt = "";
10                 if (req.HttpMethod == "POST")
11                 {
12                     var fp = "";
13                     using (var r = new StreamReader(req.InputStream, Encoding.UTF8))
14                     {
15                         fp = r.ReadToEnd();
16                     }
17                     var printer = req.QueryString["printer"];
18                     switch (req.Url.LocalPath)
19                     {
20                         case "/printZPP":
21                             printComp1.Print(fp, printer);
22                             break;
23                         case "/printTJBB":
24                             printComp1.PrintBB(fp, printer);
25                             break;
26                         case "/printQD":
27                             printComp1.PrintQd(fp, printer);
28                             break;
29                         case "/printAll":
30                             printComp1.UniversalPrint(fp, printer);
31                             break;
32                         default:
33                             //rep.StatusCode = 404;
34                             txt = "404";
35                             break;
36                     }
37                 }
38                 else
39                 {
40                     switch (req.Url.LocalPath)
41                     {
42                         case "/GetPrintNames":
43                             txt = printComp1.GetPrinterNames();
44                             break;
45                         case "/GetPrinter":
46                             {
47                                 var id = req.QueryString["id"];
48                                 txt = printComp1.GetLocalPrinter(id);
49                             }
50                             break;
51                         case "/SetPrinter":
52                             {
53                                 var id = req.QueryString["id"];
54                                 var printer = req.QueryString["printer"];
55                                 printComp1.SetLocalPrinter(id, printer);
56                             }
57                             break;
58                                 default:
59                                 txt = printComp1.GetPrinterNames();
60                                 //rep.StatusCode = 404;
61                                 txt = "404";
62                             break;
63                     }
64                 }
65 
66                 using (var w = new StreamWriter(rep.OutputStream, Encoding.UTF8))
67                 {
68                     w.WriteLine(txt);
69                 }
70             }
71         }

HTTP處理接口,PrintHandler派生此接口處理打印任務,也可以派生接口執行其他本地任務,只是簡單的處理get和post文本,沒有具體的參數解析,需要類自行解析。。。

1     //類似於MVC框架的ACTION或者CONTROLER,可派生此接口實現其他操作
2     public interface IHttpHandler
3     {
4         string Handler(string txt);//簡單的處理文本消息
5     }
IPrint打印接口,派生此接口執行具體打印任務,打印格式這塊可以封裝出一整套的處理代碼(常用的標簽,表格打印和格式設置),有空再處理了
1     //打印接口,需要打印格式,派生此接口即可
2     public interface IPrint
3     {
4         bool Print(Graphics g);//返回值為是否還有打印需要打印的頁內容,即是否打印結束
5     }

啟動本地服務器后,瀏覽器直接訪問或ajax跨域訪問本地服務器即可調用本地處理服務!

 1 $.ajax({
 2           url : "http://localhost:23333/print",
 3           type : "POST",
 4           contentType: "application/json;charset=utf-8",
 5           data : "{'name':'大蘿卜卜','age':32,'sex':true}",
 6           dataType : "text",
 7           success : function(result) {
 8             if (result == "ok") {
 9               alert("打印成功!");
10             } else {
11               alert("打印出錯:"+result )
12             }
13           },
14           error:function(msg){
15            aler('Error:'+msg);
16           }
17         })

本地測試

            var web = new WebClient();
            var txt = textBox1.Text;
            byte[] bytearray = Encoding.UTF8.GetBytes(txt);
            txt = Convert.ToBase64String(bytearray);
            txt = System.Web.HttpUtility.UrlEncode(txt, Encoding.UTF8);//必須經過url編碼
            web.Encoding = Encoding.UTF8;
            web.Headers.Add("ContentType", "application/x-www-form-urlencoded");

            try
            {
                var ret = web.UploadString("http://127.0.0.1:1234", "POST", "args=" + txt);
                textBox2.Text = Encoding.UTF8.GetString(Convert.FromBase64String(ret));

            }
            catch (WebException ex)
            {
                var rsp = ex.Response as HttpWebResponse;
                if(rsp !=null)
                {
                    var code = (int)rsp.StatusCode;
                    textBox2.Text = code + "\r\n";
                    var stream = rsp.GetResponseStream();
                    using (var s = new StreamReader(stream))
                    {
                        textBox2.Text += s.ReadToEnd();
                    }
                }
                else
                {
                    textBox2.Text = ex.Message;

                }
            }

 

為了發表博客,花了2個小時,把代碼整理,簡單的封裝成接口,平常寫代碼哪有這么費事,分分鍾寫完交差了事(意大利面條,笑),寫文章不易,點個贊吧。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM