ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 使用RSClientPrint直接打印本地RDLC报表

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

原创 Linux操作系统 作者:iDotNetSpace 时间:2010-06-21 09:15:18 0 删除 编辑
最近一个项目使用ReportViewer来呈现本地RDLC模块的报表,需要用户点击至少三次才能直正打印,用户感觉易用性很不好,需要我们修改。

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

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

代码
<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ -->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 

代码
<!--Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->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(""
);
            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}", XmlConvert.EncodeName(requestParameters.Keys[i].Substring(3
)), HttpUtility.HtmlEncode(requestParameters[i]));
                    }
                }
            }
            builder.Append(
""
);

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

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/12639172/viewspace-665757/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2008-01-04

  • 博文量
    2376
  • 访问量
    5766042