在asp.net中,新建一个handler,把需要切割的网内图片,通过调用此URL来切割并缓存。http://localhost:53829/CacheImage/ResizeImage.ashx?src=/Image/FolderLevel1FolderLevel11FolderLevel111/548974833.jpg&width=928&height=828&type=10&quality=90
注意:
1. width 和height至少有一个不为空
2. type默认为20,具体解释为:10-按宽度缩放不切高度;11-按宽度缩放切高度;20-按高度缩放不切宽度;21-按高度缩放切宽度;30-等比例缩略,高或宽不足比例补空白,不拉伸;31-拉伸原图缩略(会失真)
3. type为11,21的未实现,感觉用处不大
4.quality为压缩比率,默认为80
我的实例如下:
1.在网站根目录创建CacheImage文件夹,handler和所有的缓存文件都将存在个目录下,并按照源图片的结构缓存
2.再此文件夹下创建图片压缩处理的handler:ResizeImage.ashx
3.把CacheImage文件夹设为不需要登录权限即可访问,在web.config中配置
<location path="CacheImage"> <system.web> <authorization> <allow users="*" /> </authorization> </system.web> </location>
4.IIS中设置CacheImage的权限为可控
5.直接上Handler代码:
using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Web; using System.Web.Configuration; using log4net; namespace Alan.Web.CacheImage { /// <summary> /// 动态缩略图处理程序 /// 调用示例: <img runat="server" src="~/CacheImage/ResizeImage.ashx?src=/Image/FolderLevel1/FolderLevel11/FolderLevel111/1299906975tusPd7.jpg&width=128&height=128&type=20&quality=90" /> /// type介绍:10-按宽度缩放不切高度;11-按宽度缩放切高度;20-按高度缩放不切宽度;21-按高度缩放切宽度;30-等比例缩略,高或宽不足比例补空白,不拉伸;31-拉伸原图缩略(会失真) /// </summary> public class ResizeImage : IHttpHandler { private ILog _log = LogManager.GetLogger(typeof (ResizeImage)); public void ProcessRequest(HttpContext context) { Stream fileStream = null; try { context.Response.ContentType = "text/plain"; string fileName = context.Server.UrlDecode(context.Request["src"]); string fileNameString = fileName; if (string.IsNullOrEmpty(fileName)) { context.Response.Write("缺少参数src."); return; } //本地的图片则以/开头 if (fileName.StartsWith("/")) { fileName = System.Web.HttpContext.Current.Server.MapPath("~" + fileName); } FileInfo fi = new FileInfo(fileName); if (!fi.Exists) { context.Response.Write("图片不存在,文件名为:" + fileName); return; } Image image = Image.FromFile(fi.FullName); int sourceWidth = image.Width, sourceHeight = image.Height; if (sourceWidth == 0 || sourceHeight == 0) { context.Response.Write("错误:原始图片高度或宽度为0"); return; } string widthStr = context.Request["width"]; string heightStr = context.Request["height"]; string typeStr = context.Request["type"]; string qualityStr = context.Request["quality"]; int deliveredWidth = 0, deliveredHeight = 0, type = 20; long quality = 80;//图片质量默认为80 int.TryParse(widthStr, out deliveredWidth); int.TryParse(heightStr, out deliveredHeight); int.TryParse(typeStr, out type); long.TryParse(qualityStr, out quality); string contentType = getContentType(fi.Extension); context.Response.ContentType = contentType; //缓存图片的路径及格式:websiteurl+/CacheImage/FileName.type.deliveredHeight.deliveredWidth.quality.扩展名。(FileName包含文件夹路径) string finallyFileName = System.AppDomain.CurrentDomain.BaseDirectory + "CacheImage/" + fileNameString + "." + type + "." + deliveredHeight + "." + deliveredWidth + "." + quality + fi.Extension; //如果缓存中有照片,从缓存中读取图片信息 if (File.Exists(finallyFileName)) { try { using (Bitmap imagelocal = new Bitmap(finallyFileName)) { using (MemoryStream ms = new MemoryStream()) { imagelocal.Save(ms, System.Drawing.Imaging.ImageFormat.Png); context.Response.OutputStream.Write(ms.GetBuffer(), 0, (int) ms.Length); } } return; } catch (Exception eee) { //若发生异常,删除此文件,继续生成新文件的操作 File.Delete(finallyFileName); _log.Error(eee); } } try { int finallyWidth = 0, finallyHeight = 0; string errorMessage = string.Empty; //如果计算失败,返回错误及原因,比如以高度作为依据却把高度设为0等 if (!ComputeWidthAndHeight(sourceWidth, sourceHeight, deliveredWidth, deliveredHeight, type, ref finallyWidth, ref finallyHeight, ref errorMessage)) { context.Response.Write(errorMessage); return; } //只有在源图片大于压缩图片的前提下才会压缩,否则直接返回源图片 if (sourceWidth > deliveredWidth || sourceHeight > deliveredHeight) { Bitmap bitmap = new Bitmap(finallyWidth, finallyHeight, PixelFormat.Format32bppArgb); Graphics graphics = Graphics.FromImage(bitmap); graphics.Clear(Color.White); graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighSpeed; //平滑处理 graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; //缩放质量 graphics.DrawImage(image, new Rectangle(0, 0, finallyWidth, finallyHeight)); image.Dispose(); EncoderParameters parameters = new EncoderParameters(1); parameters.Param[0] = new EncoderParameter(Encoder.Quality, quality); //图片质量参数 //创建缓存所需的文件夹位置 int lastFolderIndex = finallyFileName.LastIndexOf("/", StringComparison.CurrentCultureIgnoreCase) > finallyFileName.LastIndexOf(@"", StringComparison.CurrentCultureIgnoreCase) ? finallyFileName.LastIndexOf("/", StringComparison.CurrentCultureIgnoreCase) : finallyFileName.LastIndexOf(@"", StringComparison.CurrentCultureIgnoreCase); string finallyFileFolder = finallyFileName.Substring(0,lastFolderIndex); //若不存在缓存文件夹,创建文件夹目录 if (!Directory.Exists(finallyFileFolder)) { Directory.CreateDirectory(finallyFileFolder); } fileStream = new FileStream(finallyFileName, FileMode.Create); if (finallyFileName.ToLower().EndsWith(".bmp")) { bitmap.Save(fileStream, System.Drawing.Imaging.ImageFormat.Png); //仅做图片裁切,不做压缩使用 } else { bitmap.Save(fileStream, GetImageCodecInfo(contentType), parameters); //用做图片质量压缩使用,通过parameters设置压缩比率,当压缩bmp图片时报错 } using (MemoryStream ms = new MemoryStream()) { if (finallyFileName.ToLower().EndsWith(".bmp")) { bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Png); //仅做图片裁切,不做压缩使用 } else { bitmap.Save(ms, GetImageCodecInfo(contentType), parameters); //用做图片质量压缩使用,通过parameters设置压缩比率,当压缩bmp图片时报错 } context.Response.OutputStream.Write(ms.GetBuffer(), 0, (int) ms.Length); } parameters.Dispose(); bitmap.Dispose(); return; } image.Dispose(); } catch (Exception eexx) { //压缩文件失败,则继续下面返回原始图片的操作 _log.Error(eexx); } //若上述有错或其他原因,返回源图片 fileStream = new FileStream(fi.FullName, FileMode.Open); byte[] bytes = new byte[(int) fileStream.Length]; fileStream.Read(bytes, 0, bytes.Length); fileStream.Close(); context.Response.BinaryWrite(bytes); } catch (Exception ex) { _log.Error(ex); context.Response.Write(ex.Message); } finally { if (fileStream != null) { fileStream.Close(); fileStream.Dispose(); } } System.GC.Collect(); } /// <summary> /// 获取文件下载类型 /// </summary> /// <param name="extension"></param> /// <returns></returns> private string getContentType(string extension) { string ct = string.Empty; switch (extension.ToLower()) { case ".jpg": ct = "image/jpeg"; break; case ".png": ct = "image/png"; break; case ".gif": ct = "image/gif"; break; case ".bmp": ct = "application/x-bmp"; break; default: ct = "image/jpeg"; break; } return ct; } //获得包含有关内置图像编码解&码&器的信息的ImageCodecInfo 对象. private ImageCodecInfo GetImageCodecInfo(string contentType) { ImageCodecInfo[] arrayICI = ImageCodecInfo.GetImageEncoders(); ImageCodecInfo jpegICI = null; for (int x = 0; x < arrayICI.Length; x++) { if (arrayICI[x].MimeType.Equals(contentType)) { jpegICI = arrayICI[x]; //设置JPEG编码 break; } } return jpegICI; } /// <summary> /// 计算压缩后图片的宽度和高度 /// </summary> /// <param name="sourceWidth">源图片宽度</param> /// <param name="sourceHeight"></param> /// <param name="deliveredWidth">传递来的图片宽度</param> /// <param name="deliveredHeight"></param> /// <param name="type">type介绍:10-按宽度缩放不切高度;11-按宽度缩放切高度;20-按高度缩放不切宽度;21-按高度缩放切宽度;30-等比例缩略,高或宽不足比例补空白,不拉伸;31-拉伸原图缩略(会失真)</param> /// <param name="finallyWidth"></param> /// <param name="finallyHeight"></param> /// <param name="errorMsg"></param> /// <returns></returns> private bool ComputeWidthAndHeight(int sourceWidth, int sourceHeight, int deliveredWidth, int deliveredHeight,int type, ref int finallyWidth, ref int finallyHeight, ref string errorMsg) { switch (type) { case 10: { if (deliveredWidth == 0) { errorMsg = "错误:缩放至目标的图片宽度为0"; return false; } finallyWidth = deliveredWidth; finallyHeight = (int)(((double)deliveredWidth/sourceWidth)*sourceHeight); } break; //case 11://TODO:11、12未做 // { // if (deliveredWidth == 0) // { // errorMsg = "错误:缩放至目标的图片宽度为0"; // return false; // } // finallyWidth = deliveredWidth; // finallyHeight = deliveredHeight; // } // break; //case 21: // { // if (deliveredHeight == 0) // { // errorMsg = "错误:缩放至目标的图片高度为0"; // return false; // } // finallyWidth = sourceWidth; // finallyHeight = deliveredHeight; // } // break; case 30: { if(deliveredHeight==0||deliveredWidth==0) { errorMsg = "错误:缩放至目标的图片高度或宽度为0"; return false; } if (((double)sourceWidth / (double)sourceHeight) > ((double)deliveredWidth / (double)deliveredHeight)) { //以宽度为基准缩小 if (sourceWidth > deliveredWidth) { finallyWidth = deliveredWidth; finallyHeight = (int)(deliveredWidth * sourceHeight / (double)sourceWidth); } else { finallyWidth = sourceWidth; finallyHeight = sourceHeight; } } else { //以高度为基准缩小 if (sourceHeight > deliveredHeight) { finallyWidth = (int)(deliveredHeight * sourceWidth / (double)sourceHeight); finallyHeight = deliveredHeight; } else { finallyWidth = sourceWidth; finallyHeight = sourceHeight; } } } break; case 31: { if (deliveredHeight == 0 || deliveredWidth == 0) { errorMsg = "错误:缩放至目标的图片高度或宽度为0"; return false; } finallyWidth = deliveredWidth; finallyHeight = deliveredHeight; } break; default://20 { if (deliveredHeight == 0) { errorMsg = "错误:缩放至目标的图片高度为0"; return false; } finallyHeight = deliveredHeight; finallyWidth = (int)((double)(deliveredHeight*sourceWidth)/sourceHeight); } break; } return true; } public bool IsReusable { get { return false; } } } }
6.调用代码如下:
<html> <body> <img height="128" width="80" src="http://admin.pl360.com/CacheImage/ResizeImage.ashx?src=/ShopData/ProductLogo/1465b59c-98f0-4c20-8002-996796db0d064.JPG&width=128&height=128&type=20&quality=90" /> </body> </html>