使用RSClientPrint直接打印本地RDLC报表


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

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

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

ExpandedBlockStart.gif 代码
<! 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 

ExpandedBlockStart.gif 代码
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,  0 0x14000 ))  >   0 )
            {
                response.OutputStream.Write(buffer, 
0 , count);
            }
        }



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

 

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

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

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

 

转载于:https://www.cnblogs.com/linwinfan/archive/2010/06/20/1761559.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值