基于HTTP可供浏览器调用的本地打印程序(简单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 }
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 $(".notice").html('Error:'+msg); 16 } 17 })
为了发表博客,花了几个小时,把代码整理,简单的封装成接口,平常写代码哪有这么费事,写完交差就完事了(意大利面条,笑),写文章不易,点个赞吧。