以前我们在.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来访问。