讨论创建基于WSE的报表打印服务及其实现


目录

  引言

  软件原理

  程序实现

  注意事项

  总结

  引言:

  WSE提供了一个非常方便的功能,就是支持附件的传输,尽管我们可以采用别的方式来达到这个目的,比如直接的返回byte型的数据,但是对于大多数应用而言,直接返回一个附件,如一张图片更为实在些,请大家不要误会我文章的标题,以为创建一个WEBSERVICE就可以方便地实现了打印了,我们的软件原理和最终打印的方式跟卢彦先生里提到的并无多大区别,我们只是利用了WebService的强大的穿透性,来使这个方式更为灵活,更易于应用和拓展,本文所采用的代码全部用C#编写。

  软件原理:

  本文采用了XML形式的数据,客户端将需要打印的数据和一些基本的参数,如图象大小,图象形式等传送给服务器端,而服务器端则根据客户端的要求生成特定的一张或多张图片返回给客户端,由客户端的打印程序统一处理,看了这个逻辑我们就可以发现:所有的业务规则完全在服务器端运做,而客户端只需要少量的代码就可以实现报表的打印。这样就避免了各种升级所带来的烦恼,当实际运用中要求增加一种或多种图表的时候,我们所需要做的只是增加或者修改服务器端的业务规则,而客户所要做的只是告诉我们要打印这种图表就可以了。

  本文采用了一些简单的XML数据,仅供示范用,客户端的Demo数据如下:

<?xml version="1.0" encoding="utf-8"?>
  <Root PrintType="line" Width="450" Height="500" Title="Print Demo">
    <Child Text="1" Value="100" Color="Black">
    </Child>
    <Child Text="2" Value="60" Color="Orange">
    </Child>
    <Child Text="3" Value="30" Color="Red">
    </Child>
    <Child Text="4" Value="40" Color="Gray">
    </Child>
    <Child Text="5" Value="90" Color="Blue">
    </Child>
    <Child Text="6" Value="60" Color="Green">
    </Child>
</Root>
其中PrintType就是客户端要求的打印类型。

  程序实现:

  服务器端代码

  本系统也同样采用了Abstract Factory的设计模式,以利于服务器端方便的扩展,此处就不再赘述。

  新建一个Web服务项目,添加抽象基类,实现类,解析类,建成后的界面如下所示:

  需要加入对Microsoft.Web.Services命名空间的引用

 

  其中

  PrintBase.cs是基类

  Parser.cs是解析类

  LinePrint.cs是实现具体图象的类

  基类代码:

  public class PrintBase
  {
    public PrintBase()
    {
      //
      // TODO: 在此处添加构造函数逻辑
      //
    }
    public virtual Stream DrawImage()
    {
      return null;
    }
}

  解析类代码:

public class Parser
  {
    public Parser()
    {
      //
      // TODO: 在此处添加构造函数逻辑
      //
    }
    public static PrintBase CreateElement(DataSet ds)
    {
      PrintBase pb = null;
      string l_strPrintType = ds.Tables["Root"].Rows[0]["PrintType"].ToString();
      switch(l_strPrintType)
      {
        case "line":
          pb = new LinePrint(ds);
          break;
        default:
          pb = new PrintBase();
          break;
      }
      return pb;
    }
}

实现类的代码:

  由于此处代码较长,我只贴出部分代码供参考,大家可以根据自己的实际情况进行图形的绘制。

/// <summary>
    /// 重载画的规则
    /// </summary>
    /// <returns>图象Stream</returns>
    public override Stream DrawImage()
    {
_ChartSize = new SizeF(float.Parse(ds.Tables["Root"].Rows[0]["Width"].ToString()),
        float.Parse(ds.Tables["Root"].Rows[0]["Height"].ToString()));
            
      Bitmap b = new Bitmap((int)_ChartSize.Width,(int)_ChartSize.Height,
        PixelFormat.Format32bppArgb);
      //初始化
      _Graphics = Graphics.FromImage(b);
      //以下省略,请自行绘制
      
      //存储返回
      MemoryStream s = new MemoryStream();
      b.Save(s,ImageFormat.Png);
      return s;
}

  我个人一直比较喜欢用DataSet操作小型的XML数据,大家请按自己喜好调整,此处展示的方法将直接供Web服务类调用。

  Web服务类的代码:

  [WebMethod]
    public bool CreateImage(DataSet ds)
    {
      bool l_bStatus = true;
      try
      {
        PrintBase pb = null;
        pb = Parser.CreateElement(ds);
        Stream s = pb.DrawImage();
        SoapContext sc = HttpSoapContext.ResponseContext;
sc.Attachments.Add(new DimeAttachment("image/png",TypeFormatEnum.MediaType,s));
      }
      catch
      {
        l_bStatus = false;
      }
      return l_bStatus;
  }

至此,我们服务器端的代码就基本完成了,下面我们来看客户端所需要做的工作,我在此处建立了一个WinForm工程来做演示用,实际运用中,则采用卢彦文章里提到的usercontrol就可以了。

  客户端代码:

private void button1_Click(object sender, System.EventArgs e)
    {
      DataSet ds = new DataSet();
      ds.ReadXml(Application.StartupPath+@"test.xml");
      PrintWebService.Proxy.Service proxy = new PrintWebService.Proxy.Service();
      proxy.CreateImage(ds);
      if (proxy.ResponseSoapContext.Attachments.Count != 0)
      {
        b = new Bitmap(proxy.ResponseSoapContext.Attachments[0].Stream);
        this.pictureBox1.Image = b;
      }      
  }

  在这里,我们用DataSet载入XML,并调用WebService返回图象Stream,可以看到,客户端的工作变得非常简单,只需要调用个WebService就可以,WSE对于附件的支持完成的很好,代码也极为的简单。我还做了一步打印预览的工作来测试我创建的图片,如下:

  至此,我们就大功告成了。

  注意事项:

  &#61618; 需在Web服务项目中的web.config内加入以下语句,以保证代码的正确运行。

  <webServices>

  <soapExtensionTypes>

  dd type="Microsoft.Web.Services.WebServicesExtension,Microsoft.Web.Services,Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"

  priority="1" group="0"/>

  </soapExtensionTypes>

  </webServices>

  否则Web服务代码里的SoapContext sc = HttpSoapContext.ResponseContext; sc将永远返回null值。

  &#61618; 尽管在我的测试下Web服务所表现出来的性能相当OK,但是在实际运用中,朋友们还得仔细测试一下才行。

  总结:

  通过上面的描述,相信大家也有同样的体会,那就是扩展非常的方便,在实际应用中,客户所要求打印的数据不会发生很大变化,而对这些数据进行的汇总、列表却有着复杂的要求,通过WebService的方式,我们把这种变化集中在服务器端,尽量减少了客户端程序的改动,服务器端完全可以采用更强大的第三方组件来实现绘图功能;对于多页打印的应用,由于WSE支持多个附件的好处,我们既可以采用一次性发送所有数据在服务器端生成对应的多个图表返回,也可以分批发送;由于采用了XML的介质,数据的采集也实现了多样化,您完全可以在A服务器上采集数据,在B服务器上实现打印。

  对于文中所涉及到的代码,有需要的朋友可来信跟我索取(wohuosile@hotmail.com),对于文中所涉及到的问题,欢迎大家到计算机世界开发者俱乐部(http://www.dev-club.com)进行探讨



相关阅读:
MX 10
解放web程序员的输入验证" target="_blank">解放web程序员的输入验证
Javascript 最简单检测网速的方法和应用
只有mdf文件的数据库附加失败的修复方法分享(置疑、只读)
织梦DedeCms v5.6/5.7 新图集页面增加图片下载功能
System Idle Process 认识与分析
HTML教程:定义列表
win2003安装卡巴斯基的方法
数组处理函数库
Taglib 原理和实现之什么是Taglib
巧用linux的link命令快速定位应用程序
8个必须掌握的CSS布局技巧
MySQL索引分析和优化解决方案
firefox下绝对定位元素重叠造成不可点击问题
快速导航
PHP MySQL HTML CSS JavaScript MSSQL AJAX .NET JSP Linux Mac ASP 服务器 CMS SQL jQuery C# C++ java Android IOS oracle MongoDB PostgreSQL SQLite 交通频道 G4722 G1875 G215 G569 G421 G6733 G7577 G8906 G1235 G4916 G7291 G1953 G245 G662 G1570 G6285 G719 G1836 G1346 G4781 G4908 G289 G6781 G9290 G7358 G1928 G1815 G325 G132 G4901 G6012 G6290 G7131 G5367 G184 G151 G5303 G1136 G6481 G7028 G575 G1744 G7660 G7693 G2344 G4937 G1234 G1814 G6252 G1492 G253 G2926 G883 G9275 G1231 G556 G241 G1306 G7646 G8103 G600 G1858 G9678 G6160 G7156 G825 G1125 G7249 G1809 G1350 G432 G9466 G7067 G785 G6404 G4663 G7008 G150 G823 G1514 G7529 G1201 G2353 G205 G7629 G9409 G6147 G677 G390 G8016 G9239 G456 G828 G8045 G491 G7145 G397 G7012 G1021 G6482 G2322 G7264 G1301 G9247 G96 G1294 G7133 G4824 G7005 G1653 G5307 G1213 G822 G4837 G1422 G411 G6227 G1571 G359 G1882 G6074 G7678 G21 G7077 G1272 G8918 G9645 G461 G1254 G1846 G8021 G7303 G1104 G76 G82 G621 G218 G8533 G2341 G8543 G555 G8013 G4802 G1364 G1153 G1342 G1861 G8905 G590 G4780 G668 G9261 G1304 G1638 G1395 G2914 G8003 G7158 G1833 G1873 G8128 G1856 G1841 G8709 G7346 G4612 G2103 G835 G8712 G381 G7240 G8932 G507 G29 G4054 G6273 G6752 G426 G211 G9473 G7119 G2333 G1567 G6153 G360 G4011 G5301 G7648 G8010 G8015 G6706 G614 G423 G8557 G9465 G72 G6018 G8901 G7030 G123

丹东 云霄 辽中 德阳 克拉玛依 惠山 招远 昭通 铁岭西 延吉西 军粮城北 定西 晋中 许昌东 郫县 诏安 七台河 高碑店东 南昌 延安 敦化 铜陵北 嵩明 鲘门 扬中 龙里北 舟山 洛阳 运城北 鞍山 西昌 邵阳北 绍兴 白山 三明 肇东 陵水 衡山西 嘉善 宜都 泰兴 泉州 汉口 东胜西 昌图西 锦州南 安阳东 怀化 黄南 亚龙湾 扬州 温州 南翔北 福安 金山北 永川东 安达 曲阜东 郑州西 天门 绍兴北 涪陵北 阳泉北 三亚 葫芦岛北 徐州 阳江 辽源 新泰 阿坝 孝感北 三穗 金寨 保山 高安 安阳 牟平 西双版纳 信阳 繁昌西 哈尔滨北 达州 新余 沈阳南 四平 扶余北 伊宁 郴州西 济源 水家湖 民权北 福鼎 如皋 奉化 全州南 安庆 太姥山 武汉 乐清 皮口 武昌 茂名 邯郸 资阳 马鞍山 三水南 泰安 包头东 衡阳东 南丰 仙桃西 安吉 罗源 山海关 平湖 惠州 资阳北 淄博 丹阳 莱州 巴东 关岭 盐城 锦州 格尔木 益阳 大英东 吉林 湛江 临安 襄汾西 渑池南 当涂东 辽阳 徐水 贺州 韶关 光明城 邯郸东 普安县 南江口 铜川 五龙背东 张家港 烟台南 萍乡北 青堆 长乐 江门 台州 衡水 湘潭北 闽清北 高邑西 盖州西 石柱县 潮汕 肇庆 泰康 邵东 湖州 余姚 平凉 宜宾 增城 沧州 都匀 防城港 鹰潭北 海东西 福田 余姚北 岳池 广州北 南安 蓬莱 瓦房店西 李石寨 葛店南 海安 无锡东 上饶 通辽 四会 桂林西 砀山南 兰州 滨海 龙口 绅坊 莱西 石林西 深圳 大连北 成都 上海西 孝感 杏树屯 德清 嘉兴

Copyright © 2016 phpStudy |