using System.Drawing; using System.Web; using cczcrv.Web.File.Uploader.Image; using System.IO; using System.Linq; using System; namespace cczcrv.Web.File.Filters { public class GetImageHandler : IHttpHandler { private int[] _imageWidthLimits = new[] { 100, 255, 320 }; public void ProcessRequest(HttpContext context) { //防盜鏈 //if (context.Request.UrlReferrer == null || !context.Request.UrlReferrer.Host.Contains("cczcrv.com")) //{ // CreateNotFoundResponse(context); // return; //} DateTime lastCacheTime; if (DateTime.TryParse(context.Request.Headers["If-Modified-Since"], out lastCacheTime)) { if ((DateTime.Now - lastCacheTime).TotalMinutes < 20) { CreateCacheResponse(context); return; } } //圖片不存在,返回默認圖片 var path = context.Server.MapPath(context.Request.Url.AbsolutePath); if (!System.IO.File.Exists(path)) { CreateNotFoundResponse(context); return; } int width = 0; var strWidth = context.Request.Params["width"]; if (!string.IsNullOrWhiteSpace(strWidth) && int.TryParse(strWidth, out width)) { //驗證請求的圖片的尺寸是否在容許的範圍內 if (!_imageWidthLimits.Contains(width)) { CreateNotFoundResponse(context); return; } var index = path.LastIndexOf('\\'); //縮略圖目錄不存在,建立目錄 var thumbnailDirectory = $"{path.Substring(0, index)}/thumb_{width}"; if (!Directory.Exists(thumbnailDirectory)) { Directory.CreateDirectory(thumbnailDirectory); } var thumbnailPath = $"{thumbnailDirectory}/{path.Substring(index + 1)}"; //縮略圖不存在,生成縮略圖 if (!System.IO.File.Exists(thumbnailPath)) { var image = Image.FromFile(path); //width大於圖片自己寬度,則返回原圖 if (width >= image.Width) { CreateImageResponse(context, path); return; } ThumbnailHelper.MakeThumbnail(image, thumbnailPath, width, 100, ThumbnailModel.W); } CreateImageResponse(context, thumbnailPath); return; } CreateImageResponse(context, path); } public bool IsReusable { get { return false; } } #region 私有方法 /// <summary> /// 返回圖片 /// </summary> /// <param name="context">當前上下文</param> /// <param name="filePath">圖片路徑</param> private void CreateImageResponse(HttpContext context, string filePath) { context.Response.Cache.SetLastModified(DateTime.Now); context.Response.ContentType = "image/JPEG"; context.Response.WriteFile(filePath); context.Response.End(); } /// <summary> /// 返回默認圖片 /// </summary> /// <param name="context">當前上下文</param> private void CreateNotFoundResponse(HttpContext context) { var path = context.Server.MapPath("/upload/image/404.png"); CreateImageResponse(context, path); } /// <summary> /// 返回緩存的內容,HttpCode等於304 /// </summary> /// <param name="context"></param> private void CreateCacheResponse(HttpContext context) { context.Response.StatusCode = 304; context.Response.End(); } #endregion } }
<add name="getImage" path="/upload/image/*" verb="GET" type="cczcrv.Web.File.Filters.GetImageHandler" />
運行效果能夠經過下面兩個連接查看:前端
原圖:http://file.cczcrv.com/upload/image/201612/15/w_1903359727.pngweb
縮略圖:http://file.cczcrv.com/upload/image/201612/15/w_1903359727.png?width=100後端
唉,受園友啓發,不能偷懶,加了width參數驗證,合法的參數包括[100,255,320]。api
這個Handler中還能夠作不少事情,好比圖片防盜鏈,ip黑名單等等,不過說到底原理只是一個IHttpHandler的應用而已。緩存