`

实战 HTTP 处理程序(HTTP Handler) (5)---不用临时文件,直接打开动态生成的文件

阅读更多

笔者是作信息系统开发的,经常要制作各种各样的报表,而且这些报表都要求能够导出成 PDF 或 Excel 文件。完成这项工作最简单的方法自然是使用 ReprotViewer 这个控件了---它提供报表预览功能,并且自带导出PDF 或 Excel 文件的功能。不过,有时我们不想在页面上放置 ReprotViewer 控件(多数都是因为页面空间有限或天杀的界面设计师没给你留放这个控件的地方),而是希望能让用户直接按一个按钮就可以预览并打印报表,请见下图:


好在 LocalReport 类提供了一个叫 Render() 的函数,可以用来实现PDF或Excel文件导出。通常的方法是:初始化LocalReport 类对象->使用 LocalReport 类的 Render() 函数导出PDF或Excel文件->将生成的文件保存在服务器硬盘的一个临时目录下->使用 javascript:window.open() 函数打开一个新的浏览器窗体->在这个新窗体中从服务器硬盘上读取刚刚生成的那个PDF或Excel文件->向 Page.Response 写入刚刚读取的文件内容->从服务器硬盘上删除这个已经没用了的PDF或Excel文件。
在这个颇为繁琐的流程里,生成一个临时的PDF或Excel文件这步让人很不舒服。首先,要在服务器的硬盘上创建一个临时文件夹。其次,要考虑多个用户同时导出临时文件时的文件重名问题。还有,文件用下载完了要删除,不然会污染环境。能不能把这步去掉呢?
答案是肯定的。我们可以先把生成的PDF文件内容保存到Session中,然后向 MyHandler.jxd 发送访问请求,在由 MyHandler.jxd 将 Session 中的文件内容发送到客户端。具体的流程是:初始化 LocalReport 类对象->使用 LocalReport 类的 Render() 函数导出PDF或Excel文件->将生成的文件内容保存到 Session 中->使用 javascript:window.open() 函数打开一个新的浏览器窗体访问 MyHandler.jxd ->MyHandler.jxd 接收到访问请求后将 Session 中的文件内容发送到客户端。具体的实现方法请看下面的源代码。

源代码

MyHandler.cs
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->usingSystem;
usingSystem.Collections.Generic;
usingSystem.Text;

usingSystem.IO;
usingSystem.Drawing;
usingSystem.Drawing.Imaging;

namespacemylib.system.web
{
publicclassMyHandler:System.Web.IHttpHandler,System.Web.SessionState.IRequiresSessionState
{
#regionIHttpHandler成员

publicboolIsReusable
{
get{returnfalse;}
}

publicstaticstringmsg
{
get{returnSystem.Web.HttpContext.Current.Session["mylib.system.web.MyHandler.msg"]asstring;}
set{System.Web.HttpContext.Current.Session["mylib.system.web.MyHandler.msg"]=value;}
}

publicstaticstringcontent_type
{
get{returnSystem.Web.HttpContext.Current.Session["mylib.system.web.MyHandler.content_type"]asstring;}
set{System.Web.HttpContext.Current.Session["mylib.system.web.MyHandler.content_type"]=value;}
}

publicstaticbyte[]content
{
get{returnSystem.Web.HttpContext.Current.Session["mylib.system.web.MyHandler.content"]asbyte[];}
set{System.Web.HttpContext.Current.Session["mylib.system.web.MyHandler.content"]=value;}
}

publicvoidProcessRequest(System.Web.HttpContextcontext)
{
context.Response.ContentType
=content_type;
context.Response.OutputStream.Write(content,
0,content.Length);

content
=null;//释放内存
}
#endregion
}
}

Default.aspx
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><%@PageLanguage="C#"AutoEventWireup="true"CodeFile="Default.aspx.cs"Inherits="_Default"%>

<%@RegisterAssembly="Microsoft.ReportViewer.WebForms,Version=8.0.0.0,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a"
Namespace
="Microsoft.Reporting.WebForms"TagPrefix="rsweb"%>

<!DOCTYPEhtmlPUBLIC"-//W3C//DTDXHTML1.0Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<htmlxmlns="http://www.w3.org/1999/xhtml">
<headrunat="server">
<title>无标题页</title>
</head>
<body>
<formid="form1"runat="server">
<div>
<asp:ButtonID="open_pdf_button"runat="server"OnClick="open_pdf_button_Click"Text="报表打印"
Width
="106px"/>
</div>
</form>
</body>
</html>

Default.aspx.cs
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->usingSystem;
usingSystem.Data;
usingSystem.Configuration;
usingSystem.Web;
usingSystem.Web.Security;
usingSystem.Web.UI;
usingSystem.Web.UI.WebControls;
usingSystem.Web.UI.WebControls.WebParts;
usingSystem.Web.UI.HtmlControls;

usingSystem.Collections.Generic;

publicpartialclass_Default:System.Web.UI.Page
{
protectedvoidPage_Load(objectsender,EventArgse)
{
}
protectedvoidopen_pdf_button_Click(objectsender,EventArgse)
{
//生成报表
Microsoft.Reporting.WebForms.LocalReportrpt
=newMicrosoft.Reporting.WebForms.LocalReport();
rpt.ReportPath
=Server.MapPath("~/Report.rdlc");

//由报表生成PDF文件,并保存在内存中
Microsoft.Reporting.WebForms.Warning[]Warnings;
string[]strStreamIds;
stringstrMimeType;
stringstrEncoding;
stringstrFileNameExtension;

byte[]bytes=rpt.Render("PDF",null,outstrMimeType,outstrEncoding,outstrFileNameExtension,
outstrStreamIds,outWarnings);

//通过Session将动态生成的PDF文件的内容与MyHandler共享
mylib.system.web.MyHandler.content_type="application/pdf";
mylib.system.web.MyHandler.content
=bytes;

//打开一个新的窗体,向MyHandler.jxd发出访问请求
if(!Page.ClientScript.IsStartupScriptRegistered(Page.GetType(),"OpenFile"))
{
Page.ClientScript.RegisterStartupScript(Page.GetType(),
"OpenFile",
"window.open('MyHandler.jxd');",true);
}
}
}

注意上面的代码中用于执行javascript语句的代码是
Page.ClientScript.RegisterStartupScript(Page.GetType(), "OpenFile",
"window.open('MyHandler.jxd');", true);
而不是用Response.Write()。这是因为使用Response.Write()函数向客户端输出信息有可能破坏HTML代码的结构!我的一个同事有一次发现她的一个Web应用程序的页面格式在设计时看起来好好的,一旦运行起来就会变得很难看。她百思不得其解,直想杀死比尔。后来发现原来是她的代码使用Response.Write()向页面输出了一些代码,只要把这些对Response.Write()调用全部换成Page.ClientScript.RegisterStartupScript() 就没问题了。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics