• 基于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 + "
    ";
                        var stream = rsp.GetResponseStream();
                        using (var s = new StreamReader(stream))
                        {
                            textBox2.Text += s.ReadToEnd();
                        }
                    }
                    else
                    {
                        textBox2.Text = ex.Message;
    
                    }
                }

    为了发表博客,花了2个小时,把代码整理,简单的封装成接口,平常写代码哪有这么费事,分分钟写完交差了事(意大利面条,笑),写文章不易,点个赞吧。

  • 相关阅读:
    [转]html之file标签 --- 图片上传前预览 -- FileReader
    常用正则表达式
    c# color 颜色代码
    WebForm 母版页使用
    iframe同域自适应问题
    完整版AJAX
    AJAX基础
    jQuery 小特效【文本框折叠隐藏,展开显示】【下拉菜单】【颜色渐变】【弹窗+遮罩】
    JQuery中的Dom操作和事件
    LINQ 【增、删、改、查】数据绑定
  • 原文地址:https://www.cnblogs.com/HelliX/p/9318008.html
Copyright © 2020-2023  润新知