以前我们在.NET里动态输出图片,往往是建一个aspx,把里面的html代码都删光,然后在cs代码里用response输出一个图片类型的stream。之后指定Image控件的url为这个aspx就行。但是,更好的做法是用ashx。
先简单介绍一下ashx:
ashx是ASP.NET里的web handler,用来处理Http请求。因为它不是aspx,所以它无需走aspx的生成过程,避免了事件、控件树等的处理,因此性能比aspx好,并且编写ashx只需要关心request的处理,不用关心web界面上的表现,有点类似JavaEE里的Servlet。动态生成图片这样的事用ashx做再好不过啦!
以我网站Web App里二维码生成器为例。原先生成图片的aspx后台代码如下:
protected void Page_Load(object sender, EventArgs e) { System.Drawing.Image image = (System.Drawing.Image)Session["tempImg"]; System.IO.MemoryStream ms = new System.IO.MemoryStream(); image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg); Response.ClearContent(); Response.ContentType = "image/Jpeg"; Response.BinaryWrite(ms.ToArray()); image.Dispose(); Session.Clear(); }
现在把它做到ashx里,完整的ashx代码如下:
<%@ WebHandler Language="C#" Class="GetQRImage" %> using System; using System.Web; public class GetQRImage : IHttpHandler, System.Web.SessionState.IReadOnlySessionState { public void ProcessRequest(HttpContext context) { System.Drawing.Image image = (System.Drawing.Image)context.Session["tempImg"]; System.IO.MemoryStream ms = new System.IO.MemoryStream(); image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg); context.Response.ClearContent(); context.Response.ContentType = "image/Jpeg"; context.Response.BinaryWrite(ms.ToArray()); image.Dispose(); context.Session.Clear(); } public bool IsReusable { get { return false; } } }
注意:
1. 因为IHttpHandler接口的约定,ashx里必须包含IsReusable的实现
2. 我需要在ashx里读取Session,所以我必须实现IReadOnlySessionState接口。如果要写Session,就要实现IRequiresSessionState接口。
3. ProcessRequest的参数是HttpContext,所以Reponse或者Session什么的请使用context来访问。