使用HTTP模块扩展 ASP.NET 处理
关于IHttpHandler的应用,我们先从它的注册方法讲起。
当你建立了一个实现了Ihttphandler接口的类后,可以在网站的web.config文件中注册这个httphandler
示例如下:
< httpHandlers > < remove verb ="*" path ="*.asmx" /> < add verb ="*" path ="*.asmx" validate ="false" type ="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /> < add verb ="*" path ="*.ho" type ="WebApplication2.HelloHandler,WebApplication2" /> </ httpHandlers >
其中最后一行 <add verb="*" path="*.ho" type="WebApplication2.HelloHandler,WebApplication2"/>便是我们手工加入的内容,WebApplication2.HelloHandler是实现了IhttpHandler接口的一个类,Path属性表示的是映射的文件格式。
这样注册好之后,如果从网站请求任何带后缀名.ho的文件时,就会转到WebApplication2.HelloHandler类进行处理。
而WebApplication2.HelloHandler的内容可以是在网页上打印一行文本(如下面代码),也可以是下载一个文件,反正在httphandler里面你可以控制response对象的输出。
下面代码示例打印一行文字的WebApplication2.HelloHandler源码:
using System; using System.Data; using System.Configuration; using System.Linq; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.HtmlControls; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Xml.Linq; namespace WebApplication2{ public class HelloHandler:IHttpHandler { #region IHttpHandler public void ProcessRequest(HttpContext context) { context.Response.ContentType = " text/html " ; context.Response.Write( " <html> " ); context.Response.Write( " <body> " ); context.Response.Write( " <b>Response by HelloHandler!</B> " ); context.Response.Write( " </body> " ); context.Response.Write( " </html> " ); } public bool IsReusable { get { return true ; } } #endregion }}
以下内容为转载的IhttpHandler示例:利用IhttpHandler实现文件下载
1. 首先新建一个用于下载文件的page页,如download.aspx,里面什么东西也没有。 2. 添加一个DownloadHandler类,它继承于IHttpHandler接口,可以用来自定义HTTP 处理程序同步处理HTTP的请求。
using System.Web; using System; using System.IO; public class DownloadHandler : IHttpHandler{ public void ProcessRequest(HttpContext context) { HttpResponse Response = context.Response; HttpRequest Request = context.Request; System.IO.Stream iStream = null ; byte [] buffer = new Byte[ 10240 ]; int length; long dataToRead; try { string filename = FileHelper.Decrypt(Request[ " fn " ]); // 通过解密得到文件名 string filepath = HttpContext.Current.Server.MapPath( " ~/ " ) + " files/ " + filename; // 待下载的文件路径 iStream = new System.IO.FileStream(filepath, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read); Response.Clear(); dataToRead = iStream.Length; long p = 0 ; if (Request.Headers[ " Range " ] != null ) { Response.StatusCode = 206 ; p = long .Parse(Request.Headers[ " Range " ].Replace( " bytes= " , "" ).Replace( " - " , "" )); } if (p != 0 ) { Response.AddHeader( " Content-Range " , " bytes " + p.ToString() + " - " + (( long ) (dataToRead - 1 )).ToString() + " / " + dataToRead.ToString()); } Response.AddHeader( " Content-Length " , (( long ) (dataToRead - p)).ToString()); Response.ContentType = " application/octet-stream " ; Response.AddHeader( " Content-Disposition " , " attachment; filename= " + System.Web.HttpUtility.UrlEncode(System.Text.Encoding.GetEncoding( 65001 ).GetBytes(Path.GetFileName(filename)))); iStream.Position = p; dataToRead = dataToRead - p; while (dataToRead > 0 ) { if (Response.IsClientConnected) { length = iStream.Read(buffer, 0 , 10240 ); Response.OutputStream.Write(buffer, 0 , length); Response.Flush(); buffer = new Byte[ 10240 ]; dataToRead = dataToRead - length; } else { dataToRead = - 1 ; } } } catch (Exception ex) { Response.Write( " Error : " + ex.Message); } finally { if (iStream != null ) { iStream.Close(); } Response.End(); } } public bool IsReusable { get { return true ; } }} 3. 这里涉及到一个文件名加解密的问题,是为了防止文件具体名称暴露在状态栏中,所以添加一个FileHelper类,代码如下:
public class FileHelper{ public static string Encrypt( string filename) { byte [] buffer = HttpContext.Current.Request.ContentEncoding.GetBytes(filename); return HttpUtility.UrlEncode(Convert.ToBase64String(buffer)); } public static string Decrypt( string encryptfilename) { byte [] buffer = Convert.FromBase64String(encryptfilename); return HttpContext.Current.Request.ContentEncoding.GetString(buffer); }} 利用Base64码对文件名进行加解密处理。 4. 在Web.config上,添加httpHandlers结点,如下:
<system.web> <httpHandlers> <add verb="*" path="download.aspx" type="DownloadHandler" /> </httpHandlers></system.web>
5. 现在新建一个aspx页面,对文件进行下载: Default.aspx代码如下:
Code <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %> <!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 runat="server"> <title>文件下载</title></head><body> <form id="form1" runat="server"> <div> <asp:HyperLink ID="link" runat="server" Text="文件下载"></asp:HyperLink> </div> </form></body></html> Default.aspx.cs代码如下:
using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; public partial class _Default : System.Web.UI.Page{ protected void Page_Load( object sender, EventArgs e) { string url = FileHelper.Encrypt( " DesignPattern.chm " ); link.NavigateUrl = " ~/download.aspx?fn= " + url; }} 这样就实现了文件下载时,不管是什么格式的文件,都能够弹出打开/保存窗口。
转载于:https://www.cnblogs.com/tuyile006/archive/2009/10/14/1583029.html
相关资源:数据结构—成绩单生成器