使用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"> ITPUB个人空间Guv%iCk`{0C
<html xmlns="http://www.w3.org/1999/xhtml"> ITPUB个人空间W7W"q LQ/
<head>
7I$bD8~]Y9_0    
<title>title> ITPUB个人空间 ~AgO6R5y
head>
$dE:O1cD-Rrn0
<BODY onload="Print()"> ITPUB个人空间CL/k2U6p
                
<OBJECT ID="RSClientPrint" ITPUB个人空间z#E~4i-y.YZo(Y [:W
classid
="CLSID:5554DCB0-700B-498D-9B58-4E40E5814405" CODEBASE="/RSClientPrint-x86.cab" VIEWASTEXT>OBJECT>
`LKl7eacV%a3}0                
<script type="text/javascript" language="javascript">
/H%Q0t)bI'j2{0                    
function  Print(oid,name) {ITPUB个人空间$AeW"P)J&f
                        
if (typeof RSClientPrint.Print == "undefined"
) {
'KF1AvCG1cui,f!T8X0                            alert(
"Unable to load client print control."
);ITPUB个人空间d"}1I/@
                            
return
;
S.[P"|%iJ/S0                        }
0f(b/` fp:G8z|0                        RSClientPrint.MarginLeft 
= 0
;ITPUB个人空间 T#X/ycZ#G3K
                        RSClientPrint.MarginTop 
= 0
;ITPUB个人空间cTt p,l7?h
                        RSClientPrint.MarginRight 
= 0
;
6gU}Z1?Mr0                        RSClientPrint.MarginBottom 
= 0
;ITPUB个人空间+W_#M ko A/q}
                        RSClientPrint.PageHeight 
= 296.926
;ITPUB个人空间 Kuhh [$@6/
                        RSClientPrint.PageWidth 
= 210.058
;
'e$[.E#B#Jr5HI0
XlR3s cg m0                        RSClientPrint.Culture 
= 2052
;ITPUB个人空间Y vi.|`L7e&D#k;U
                        RSClientPrint.UICulture 
= 2052
;ITPUB个人空间 w/H^'s)TY
                        RSClientPrint.UseSingleRequest 
= true
;
FT'`u;Q7X0                        RSClientPrint.UseEmfPlus 
= true
;ITPUB个人空间+n,A_+??
                        
oA~[ BB0                        RSClientPrint.Print(
"http://localhost:2940/JDCJY/ReportHandler.ashx""oid="+escape(oid)+"&name="+escape(name), "test"
);ITPUB个人空间2sjYZdg:j
                    }
%A0iC+SjNF,K0                
script> ITPUB个人空间Y|4PEqk&Y5F
ITPUB个人空间 F[&NG|
ITPUB个人空间 CPJR0X H$E

[ G*~wA&p5|0                
x*N nZ(s0ITPUB个人空间9MB6G ?Q6x^

z z_l0R.Caw4Q+Z0ITPUB个人空间?j[V ^ zP6N
                
BODY>
s@0m3abL0
html>

 

  然后实现ReportHandler.ashx 

 

代码
public class  ReportHandler : IHttpHandler
"@L#g7d0_|&[.fO[o~0    {
6L8NC l[L*F K)C0
G(Q2x-D(l9xe8kh0        
public void
 ProcessRequest(HttpContext context)ITPUB个人空间O6UL~]1R]&DM0?-_
        {ITPUB个人空间.FH[^y,KZ#f

5Qc_.a;]0            Warning[] warningArray;ITPUB个人空间$HH(T'/)?g.uM
            HttpResponse response 
=
 context.Response;
F2q2N%r+u6bf1l0            response.StatusCode 
= 200
;
.MSw LJU1@0            MemoryStream lastMemoryStream 
= null
;ITPUB个人空间,Ce"U}p8O+kc~5R^
            context.Response.BufferOutput 
= false
;
N8{1K]'~Oh n%zfg0            context.Response.ContentType 
= null
;ITPUB个人空间]M,VR.}3tW#/F
            context.Response.Expires 
= -1
;ITPUB个人空间I e'].{Z%k X

we6L']c zp$C0            var ds 
= new
 DataSet();
*V&S%^3l./.L_(r4`!r$P0            LocalReport localReport 
= new
 LocalReport();
}1{,E0D8{-F0            localReport.ReportEmbeddedResource 
= string.Format("{0}.rdlc", context.Request.QueryString["name"
]);
V"F4Qr,Le K!B4c:O0            localReport.DataSources.Add(
new Microsoft.Reporting.WebForms.ReportDataSource("ds"
, ds));ITPUB个人空间G"~Zdf@y
            StringBuilder builder 
= new StringBuilder(""
);ITPUB个人空间*} q*HK A)G a#Bo
            NameValueCollection requestParameters 
=
 context.Request.QueryString ;ITPUB个人空间w5h}r1Zy&q
            
for (int i = 0; i < requestParameters.Count; i++
)ITPUB个人空间7b)w E}#A
            {ITPUB个人空间6{6T&LK9N/v
                
if (requestParameters.Keys[i] != null
)
:Hu4Kq ?2W0                {ITPUB个人空间$Go sZM bR ?
                    
if (requestParameters.Keys[i].StartsWith("rc:"
, StringComparison.OrdinalIgnoreCase))ITPUB个人空间t-q ua@7K
                    {
%?na;XUZp0                        builder.AppendFormat(
"<{0}>{1}", XmlConvert.EncodeName(requestParameters.Keys[i].Substring(3
)), HttpUtility.HtmlEncode(requestParameters[i]));
Q/_$_n9g_p$g)R0                    }
K]"BNi{0                }
eF-F"B]*Y7IKC0            }ITPUB个人空间/NiE`"X JA}
            builder.Append(
""
);ITPUB个人空间F"_8FZ-H"Qi)S

f)F P)m / D+r0            localReport.Render(
"IMAGE", builder.ToString(), delegate(string name, string extension, Encoding encoding, string mimeType, bool
 willSeek)
GD Ik-wN0            {
/-n_0jzu(e0                
if (!
HttpContext.Current.Response.IsClientConnected)ITPUB个人空间)Mw oz;s;k
                {
i`F*DS oV ]6H)Y0                    
throw new HttpException("Client disconnected"
);
+Vq,G#]D/J0z/`*i0                }ITPUB个人空间voq+K6i&/#{
                
if (lastMemoryStream != null
)
+Ob:l0LfO c0                {
&t*k:~"`(g H0                    
this
.SendPrintStream(lastMemoryStream, response);ITPUB个人空间.k+Z_SK&k
                    lastMemoryStream.Dispose();
,S)P#RcFo:@y0                    lastMemoryStream 
= null
;ITPUB个人空间S]$[ /XY
                }ITPUB个人空间*`m/?z9Q!u*y/Z _g^+VY
                lastMemoryStream 
= new
 MemoryStream();
6M,fq]G&^0                
return
 lastMemoryStream;ITPUB个人空间 /6Xp'v2e
            }, 
out
 warningArray);
$~w4Wv"GJ H A^7cd0            
this
.SendPrintStream(lastMemoryStream, response);ITPUB个人空间[@"l1S@"O$I:T
            lastMemoryStream.Dispose();
(R-/hd6Oe0            
this.SendPrintStream(null
, response);
3`NQ0Pb8c!gB~0
G*vLM6o0c'T0            
if (!
response.BufferOutput)ITPUB个人空间#L3s!J9l.h'SU
            {
pvZ)Hy3GJ0                
string a = context.Request.ServerVariables["SERVER_PROTOCOL"
];ITPUB个人空间Y)a%au~5q
                
if (string.Equals(a, "HTTP/1.0"
, StringComparison.OrdinalIgnoreCase))ITPUB个人空间%y%yLR1_m&n k
                {ITPUB个人空间!XGt/!~v
                    context.Response.Close();
%b E*k$ba2c | t0                }ITPUB个人空间m-BKK5F U2X'/
            }
W } W ?(^%s0
Zs7eqT&i0        }
,I~"bH YIu D^1D5dp0
Y3s C8H8h0        
private void
 SendPrintStream(Stream stream, HttpResponse response)
i%zr0@3Tp(M0        {
8W YvLQ-b/S3J'o1YOn7_0            
int length = 0
;ITPUB个人空间F%Y"c5u U(@Q1hc
            
if (stream != null
)ITPUB个人空间/IF6o+t$O5f,m6T
            {
+W,F _"d0Cn:W~0                length 
= (int
)stream.Length;ITPUB个人空间5P q.@ ~d`"C&O&O
            }ITPUB个人空间 RK-`|-EZid$t
            
foreach (byte num2 in
 BitConverter.GetBytes(length))ITPUB个人空间v9]h$f#M2N/0p#r/f)l"g
            {ITPUB个人空间w"|Q@;ZJ/,A
                response.OutputStream.WriteByte(num2);ITPUB个人空间|ijs^*IG%W
            }
^{Y?n'h1T)U3^0            
if (stream != null
)ITPUB个人空间 N0GH3@d T9@/ iC N
            {ITPUB个人空间3_*KArC.@1]F_ k&~
                stream.Position 
= 0L
;
)`7})}j`v)G1cr$}Q$}0                StreamToResponse(stream, response);
%K-Z x`.{0eb*l`"i2V0                response.Flush();ITPUB个人空间 ek&I!W0sD w
            }ITPUB个人空间B~!O*~.nZ |,}4c
        }ITPUB个人空间o,vz:E;s;[
ITPUB个人空间&N B?okL VC2W
        
internal static void
 StreamToResponse(Stream data, HttpResponse response)
_/`Fj$W} o!r0        {ITPUB个人空间~y s w-M xNq(F|
            
int count = 0
;
7Zv)pliiW0            
byte[] buffer = new byte[0x14000
];
$E#r;z c&F/b5q2O!Q0            
while ((count = data.Read(buffer, 00x14000)) > 0
)
+_ s1FuMpiTY0            {ITPUB个人空间E}^+b'yQ;m
                response.OutputStream.Write(buffer, 
0
, count);
4h'D w[E.w.Y0            }
?%fU0h|^ R0        }
$I7A4e2nQN$M0
M} ^w9jr ap%?0
7fC7|SOE9Zk0
#yn CRlcq0        
public bool
 IsReusableITPUB个人空间`%?~&v#E-Xm)@oT
        {ITPUB个人空间;c'|.B'f&PI
            
get
ITPUB个人空间$k+@2p%C u&J
            {ITPUB个人空间S.Q| `1y T~v|
                
return true ;
n*wT mDEL0            }ITPUB个人空间A1j"g)T}eMl!ya,cc
        }
"/bf E:vb^z0    }

 

 

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

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

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

 

 

source: http://space.itpub.net/12639172/viewspace-665757

 

 

你可能感兴趣的:(Asp.Net)