zoukankan      html  css  js  c++  java
  • 使用RSClientPrint直接打印本地RDLC报表


      最近一个项目使用ReportViewer来呈现本地RDLC模块的报表,需要用户点击至少三次才能直正打印,用户感觉易用性很不好,需要我们修改。

      经过网上查找相关资料,发现直接使用ACTIVEX控件RSClientPrint直接打印使用SQLSERVER报表服务的资料很多,也说的比较详细,可唯独没打印本地报表的相关内容,看来只能自已摸索了。

      经过研究有关打印SQLSERVER报表服务的资料,特别是这篇文章:http://www.codeproject.com/KB/reporting-services/RsClientPrint.aspx,决下先写一个简单的HTML文 件测试一下:

    代码
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        
    <title></title>
    </head>
    <BODY onload="Print()">
                    
    <OBJECT ID="RSClientPrint"
    classid
    ="CLSID:5554DCB0-700B-498D-9B58-4E40E5814405" CODEBASE="/RSClientPrint-x86.cab" VIEWASTEXT></OBJECT>
                    
    <script type="text/javascript" language="javascript">
                        
    function Print(oid,name) {
                            
    if (typeof RSClientPrint.Print == "undefined") {
                                alert(
    "Unable to load client print control.");
                                
    return;
                            }
                            RSClientPrint.MarginLeft 
    = 0;
                            RSClientPrint.MarginTop 
    = 0;
                            RSClientPrint.MarginRight 
    = 0;
                            RSClientPrint.MarginBottom 
    = 0;
                            RSClientPrint.PageHeight 
    = 296.926;
                            RSClientPrint.PageWidth 
    = 210.058;

                            RSClientPrint.Culture 
    = 2052;
                            RSClientPrint.UICulture 
    = 2052;
                            RSClientPrint.UseSingleRequest 
    = true;
                            RSClientPrint.UseEmfPlus 
    = true;
                            
                            RSClientPrint.Print(
    "http://localhost:2940/JDCJY/ReportHandler.ashx""oid="+escape(oid)+"&name="+escape(name), "test");
                        }
                    
    </script>



                    



                    
    </BODY>
    </html>

      然后实现ReportHandler.ashx 

    代码
    public class ReportHandler : IHttpHandler
        {

            
    public void ProcessRequest(HttpContext context)
            {

                Warning[] warningArray;
                HttpResponse response 
    = context.Response;
                response.StatusCode 
    = 200;
                MemoryStream lastMemoryStream 
    = null;
                context.Response.BufferOutput 
    = false;
                context.Response.ContentType 
    = null;
                context.Response.Expires 
    = -1;

                var ds 
    = new DataSet();
                LocalReport localReport 
    = new LocalReport();
                localReport.ReportEmbeddedResource 
    = string.Format("{0}.rdlc", context.Request.QueryString["name"]);
                localReport.DataSources.Add(
    new Microsoft.Reporting.WebForms.ReportDataSource("ds", ds));
                StringBuilder builder 
    = new StringBuilder("<DeviceInfo>");
                NameValueCollection requestParameters 
    = context.Request.QueryString ;
                
    for (int i = 0; i < requestParameters.Count; i++)
                {
                    
    if (requestParameters.Keys[i] != null)
                    {
                        
    if (requestParameters.Keys[i].StartsWith("rc:", StringComparison.OrdinalIgnoreCase))
                        {
                            builder.AppendFormat(
    "<{0}>{1}</{0}>", XmlConvert.EncodeName(requestParameters.Keys[i].Substring(3)), HttpUtility.HtmlEncode(requestParameters[i]));
                        }
                    }
                }
                builder.Append(
    "</DeviceInfo>");

                localReport.Render(
    "IMAGE", builder.ToString(), delegate(string name, string extension, Encoding encoding, string mimeType, bool willSeek)
                {
                    
    if (!HttpContext.Current.Response.IsClientConnected)
                    {
                        
    throw new HttpException("Client disconnected");
                    }
                    
    if (lastMemoryStream != null)
                    {
                        
    this.SendPrintStream(lastMemoryStream, response);
                        lastMemoryStream.Dispose();
                        lastMemoryStream 
    = null;
                    }
                    lastMemoryStream 
    = new MemoryStream();
                    
    return lastMemoryStream;
                }, 
    out warningArray);
                
    this.SendPrintStream(lastMemoryStream, response);
                lastMemoryStream.Dispose();
                
    this.SendPrintStream(null, response);

                
    if (!response.BufferOutput)
                {
                    
    string a = context.Request.ServerVariables["SERVER_PROTOCOL"];
                    
    if (string.Equals(a, "HTTP/1.0", StringComparison.OrdinalIgnoreCase))
                    {
                        context.Response.Close();
                    }
                }

            }

            
    private void SendPrintStream(Stream stream, HttpResponse response)
            {
                
    int length = 0;
                
    if (stream != null)
                {
                    length 
    = (int)stream.Length;
                }
                
    foreach (byte num2 in BitConverter.GetBytes(length))
                {
                    response.OutputStream.WriteByte(num2);
                }
                
    if (stream != null)
                {
                    stream.Position 
    = 0L;
                    StreamToResponse(stream, response);
                    response.Flush();
                }
            }

            
    internal static void StreamToResponse(Stream data, HttpResponse response)
            {
                
    int count = 0;
                
    byte[] buffer = new byte[0x14000];
                
    while ((count = data.Read(buffer, 00x14000)) > 0)
                {
                    response.OutputStream.Write(buffer, 
    0, count);
                }
            }



            
    public bool IsReusable
            {
                
    get
                {
                    
    return true;
                }
            }
        }

       再后经测试,直接加载上面的HTML页面就会提示直接打印。整个过程花了不少时间,有几个地方需要注意:

    1.在服务器端生成DEVICEINFO时一定要使用上面所示的方法,我在测试过程中为了图简单,直接使用我原来在WINFORM写的一个代码,固定的DEVICEINFO信息,结果打印出来时始终会重复,不知道是怎么回事,经过使用Reflector反编译Microsoft.ReportViewer.WebForms,仔细这里面实现的报表相关服务,发现这点实现的区别,才最终搞定问题

    2.服务器代码生成EMF流如果有问题,客户端会报一个错误代码,这时你很可能会以为是客户端的错误,我开始就是,因为报错误的速度太快了。我上网对对应问题代码的资料也没有明确结果,最后看还是直接跟踪代码试试,发现是服务器端代码有些问题。

  • 相关阅读:
    金额与数字转化常用实用几个JS方法
    Jdb命令 The Java Debugger
    GLOBAL TEMPORARY TABLE
    安装与配置Nginx
    MySQL二进制安装与密码破解
    基于FPM构建企业RPM包
    安装Tomcat
    nginx配置优化
    DHCP原理及配置(三个小实验)
    DNS主、从服务器的配置
  • 原文地址:https://www.cnblogs.com/linwinfan/p/1761559.html
Copyright © 2011-2022 走看看