你的位置:首页 > ASP.net教程

[ASP.net教程]我心中的核心组件~HttpHandler和HttpModule实现图像的缩放与Url的重写


回到目录

说在前

对于资源列表页来说,我们经常会把图像做成N多种,大图,小图,中图等等,很是麻烦,在数据迁移时,更是一种痛快,而如果你把图像资源部署到nginx上,那么这种图像缩放就变得很容易了,因为它有自己的过滤器来实现这个功能,只要程序员简单的配置即可(GraphicsMagick),其实在nginx上实现缩略图的方式有很多,而对于IIS服务来说,实现这种缩略图就没有直接的方法了,必须开发人员自己写代码来实现,下面解释两个比较早的技术(被执行的期间比较早,在页面渲染之前)HttpModule和httpHandler,这两个东西我在之前的文章中也已经讲过,细节不再重复。[HttpModule几大事件,HttpHandler实现图像防盗链]

做在后

一 HttpModule对URL地址进行重写,将扩展名为jpg,jpeg,png,gif结尾的URL地址进行复写,让它支持漂亮的缩略图参数,如原地址为:new1.jpg,实现缩略图原地址为:new1.jpg?w=100&h=100,进行Url重写后的漂亮地址为:new1_100x100.jpg,怎么样,是否是很漂亮,有点像MVC 的router吧,呵呵

  /// <summary>  /// 实现URL的重写  /// </summary>  public class UrlRewriteModule : IHttpModule  {    #region IHttpModule 成员    public void Init(HttpApplication context)    {      context.BeginRequest += new EventHandler(Application_BeginRequest);    }    /// <summary>    /// url重写    /// .png?w=100&h=100    /// _100x100.png    /// </summary>    /// <param name="sender"></param>    /// <param name="e"></param>    protected void Application_BeginRequest(Object sender, EventArgs e)    {      string oldUrl = HttpContext.Current.Request.RawUrl;      if (oldUrl.LastIndexOf(".") > -1)      {        string ext = oldUrl.Substring(oldUrl.LastIndexOf(".")).ToLower();        //是图像文件        if (ext == ".jpg"          ||          ext == ".jpeg"          ||          ext == ".png"          ||          ext == "gif")        {          var param = oldUrl.Substring(oldUrl.LastIndexOf("_") + 1, (oldUrl.IndexOf(".") - oldUrl.LastIndexOf("_") - 1)).Split(new char[] { 'x' }, StringSplitOptions.RemoveEmptyEntries);          //有图像缩放请求          if (oldUrl.LastIndexOf("_") > -1)          {            string newUrl = oldUrl.Substring(0, oldUrl.LastIndexOf("_"));            newUrl = string.Format(newUrl + ".png?w={0}&h={1}", param[0], param[1]);            //将请求中的URL进行重写             HttpContext.Current.RewritePath(newUrl);          }        }      }    }    #endregion    #region IHttpModule 成员    public void Dispose()    {    }    #endregion  }

二 使用HttpHandler进行对图像的缩放,你的服务器是指与图像资源在一起的那台电脑

  /// <summary>  /// 图片动态缩放处理程序  /// </summary>  public class ImageScalingHandler : IHttpHandler  {    /// <summary>    /// 图像等比例缩放,图像默认为白色    /// </summary>    /// <param name="image"></param>    /// <param name="width"></param>    /// <param name="height"></param>    /// <returns></returns>    private Bitmap CreateThumbnail(Image image, int width, int height)    {      Point point = new Point(0, 0); //图像从那个坐标点进行截取      double wRate = 1, hRate = 1, setRate = 1;      int newWidth = 0, newHeight = 0;      try      {        if (width == 0) width = image.Width;        if (height == 0) height = image.Height;        if (image.Height > height)        {          hRate = (double)height / image.Height;        }        if (image.Width > width)        {          wRate = (double)width / image.Width;        }        if (wRate != 1 || hRate != 1)        {          if (wRate > hRate)          {            setRate = hRate;          }          else          {            setRate = wRate;          }        }        newWidth = (int)(image.Width * setRate);        newHeight = (int)(image.Height * setRate);        if (height > newHeight)        {          point.Y = Convert.ToInt32(height / 2 - newHeight / 2);        }        if (width > newWidth)        {          point.X = Convert.ToInt32(width / 2 - newWidth / 2);        }        Bitmap bit = new Bitmap(width, height);        Rectangle r = new Rectangle(point.X, point.Y, (int)(image.Width * setRate), (int)(image.Height * setRate));        Graphics g = Graphics.FromImage(bit);        g.Clear(Color.White);        g.DrawImage(image, r);        g.Dispose();        return bit;      }      catch (Exception)      {        throw;      }    }    /// <summary>    /// 处理请求    /// </summary>    /// <param name="context"></param>    public void ProcessRequest(HttpContext context)    {      int w = 0, h = 0;      int.TryParse(context.Request.QueryString["w"], out w);      int.TryParse(context.Request.QueryString["h"], out h);      Image image = Image.FromFile(context.Request.PhysicalPath);      context.Response.ContentType = "image/jpeg";      Bitmap bitMap = CreateThumbnail(image, w, h);      bitMap.Save(context.Response.OutputStream, ImageFormat.Jpeg);      image.Dispose();      bitMap.Dispose();      context.Response.End();    }    public bool IsReusable    {      get { return false; }    }  }

三 最后就是在Module和Handler的入口配置的,即如何将它们加入到当然网站中,我们采用web.config配置的方法

 <system.web>  <httpModules>   <!-- this is for Classic mode and Cassini -->   <add name="UrlRewriteModule" type="EntityFrameworks.Web.Core.HttpModules.UrlRewriteModule,EntityFrameworks.Web.Core" />  </httpModules> </system.web>

<system.webServer>  <modules runAllManagedModulesForAllRequests="true" >   <!--This is for Integrated mode-->   <add name="UrlRewriteModule" type="EntityFrameworks.Web.Core.HttpModules.UrlRewriteModule,EntityFrameworks.Web.Core" />  </modules>  <handlers>   <add name="ImageFunction1" path="*.jpg" verb="GET" type="EntityFrameworks.Web.Core.HttpHandlers.ImageScalingHandler,EntityFrameworks.Web.Core" />   <add name="ImageFunction2" path="*.png" verb="GET" type="EntityFrameworks.Web.Core.HttpHandlers.ImageScalingHandler,EntityFrameworks.Web.Core" />   <add name="ImageFunction3" path="*.gif" verb="GET" type="EntityFrameworks.Web.Core.HttpHandlers.ImageScalingHandler,EntityFrameworks.Web.Core" />   <add name="ImageFunction4" path="*.jpeg" verb="GET" type="EntityFrameworks.Web.Core.HttpHandlers.ImageScalingHandler,EntityFrameworks.Web.Core" /></handlers>

从上面的代码中,我们可以看到,对于modules来说,那有两种方式注入,一为IIS经典模式下的,另一种是IIS集成模式下的,我们需要分别进行配置。

可以看一下效果,成功的喜悦!

回到目录