博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
网站性能优化:动态缩略图技术实现思路
阅读量:6713 次
发布时间:2019-06-25

本文共 8378 字,大约阅读时间需要 27 分钟。

在网站开发过程中,大家都是如何解决多尺寸图片缩略图问题的呢?犹为典型的是电商网站,据了解,淘宝的图片缩略图是直接存储多张缩略图的方式,以满足各种情况下使用,因为它有牛逼的开源+自主开发的海量图片存储架构作支撑。但是,我们在做网站时,并不可能直接搬牛逼的架构过来,就可以达到预期的效果,况且各种成本投入也是有限的。所以一般性能优化的原则大都是这样:先考虑软件的优化,再考虑硬件的升级,当然土豪客户则除外。

  很多网站可能没有对图片进行缩略图处理,上传时图片可能几百KB,在页面也是直接加载几百KB的图片大小,这样极为占用带宽,影响网站加载速度。也有很多网站的做法可能也是直接根据前端页面所需求图片的尺寸,在上传时就处理生成相应尺寸的缩略图,但如果前端页面布局进行调整时,可能就得调整缩略图生成的尺寸,之前生成的图片也有可能需要重新生成。之前我在一个网站项目时就遇到这样的问题,经过一系列地验证,最终是采用动态缩略图技术解决的,现在整理出来给大家分享分享。

  其实,原理很简单,通过高性能的图片压缩算法,在一般处理程序(HttpHandler)对图片进行压缩处理,图片路径则直接指向HttpHandler,将图片路径、需要压缩的宽高等参数传进去,实现动态压缩。

  在网站目录下新建 ResizeImage.ashx 文件,代码如下:

1 using System;  2 using System.Collections.Generic;  3 using System.Linq;  4 using System.Web;  5 using System.IO;  6 using System.Drawing.Imaging;  7 using System.Drawing;  8   9 namespace www.ideek.cn 10 { 11     ///  12     /// 动态缩略图处理程序 13     /// 调用示例:  14     ///  15     public class ResizeImageHandler : IHttpHandler 16     { 17         public void ProcessRequest(HttpContext context) 18         { 19             context.Response.ContentType = "text/plain"; 20             string fileName = context.Server.UrlDecode(context.Request["src"]); 21             if (string.IsNullOrEmpty(fileName)) 22             { 23                 context.Response.Write("缺少参数src."); 24                 return; 25             } 26             fileName = Server.MapPath("~/" + fileName); 27  28             Stream fileStream = null; 29             try 30             { 31                 string wStr = context.Request["width"]; 32                 string hStr = context.Request["height"]; 33                 int width = 0, height = 0; 34                 if (!string.IsNullOrEmpty(wStr) && !string.IsNullOrEmpty(hStr)) 35                 { 36                     int.TryParse(wStr, out width); 37                     int.TryParse(hStr, out height); 38                 } 39  40                 FileInfo fi = new FileInfo(fileName); 41                 if (!fi.Exists) 42                 { 43                     context.Response.Write("图片不存在."); 44                     return; 45                 } 46                 string contentType = getContentType(fi.Extension); 47                 context.Response.ContentType = contentType; 48  49                 //只能处理jpg及png图片格式,没有宽高参数不进行缩放处理 50                 if (width > 0 && height > 0 && (contentType.Contains("jpeg") || contentType.Contains("png"))) 51                 { 52                     Image image = Image.FromFile(fi.FullName); 53                     int sWidth = image.Width, sHeight = image.Height; 54                     int nWidth = 0, nHeight = 0; 55                     if (sWidth > width || sHeight > height) 56                     { 57                         if (((double)sWidth / (double)sHeight) > ((double)width / (double)height)) 58                         { 59                             //以宽度为基准缩小 60                             if (sWidth > width) 61                             { 62                                 nWidth = width; 63                                 nHeight = (int)(width * sHeight / (double)sWidth); 64                             } 65                             else 66                             { 67                                 nWidth = sWidth; 68                                 nHeight = sHeight; 69                             } 70                         } 71                         else 72                         { 73                             //以高度为基准缩小 74                             if (sHeight > height) 75                             { 76                                 nWidth = (int)(height * sWidth / (double)sHeight); 77                                 nHeight = height; 78                             } 79                             else 80                             { 81                                 nWidth = sWidth; 82                                 nHeight = sHeight; 83                             } 84                         } 85  86                         Bitmap bitmap = new Bitmap(nWidth, nHeight, PixelFormat.Format32bppArgb); 87                         Graphics graphics = Graphics.FromImage(bitmap); 88                         graphics.Clear(Color.White); 89                         graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighSpeed;  //平滑处理 90                         graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;  //缩放质量 91                         graphics.DrawImage(image, new Rectangle(0, 0, nWidth, nHeight)); 92                         image.Dispose(); 93  94                         EncoderParameters parameters = new EncoderParameters(1); 95                         parameters.Param[0] = new EncoderParameter(Encoder.Quality, ((long)80));  //图片质量参数 96  97                         fileStream = new MemoryStream(); 98                         bitmap.Save(fileStream, GetImageCodecInfo(contentType), parameters); 99                         using (MemoryStream ms = new MemoryStream())100                         {101                             bitmap.Save(ms, GetImageCodecInfo(contentType), parameters);102                             context.Response.OutputStream.Write(ms.GetBuffer(), 0, (int)ms.Length);103                         }104                         parameters.Dispose();105                         bitmap.Dispose();106                         return;107                     }108                     if (image != null)109                         image.Dispose();110                 }111                 else112                 {113                     fileStream = new FileStream(fi.FullName, FileMode.Open);114                     byte[] bytes = new byte[(int)fileStream.Length];115                     fileStream.Read(bytes, 0, bytes.Length);116                     fileStream.Close();117                     context.Response.BinaryWrite(bytes);118                 }119             }120             catch (Exception ex)121             {122                 context.Response.Write(ex.Message);123             }124             finally125             {126                 if (fileStream != null)127                 {128                     fileStream.Close();129                     fileStream.Dispose();130                 }131             }132             System.GC.Collect();133         }134 135 136         /// 137         /// 获取文件下载类型138         /// 139         /// 140         /// 
141 private string getContentType(string extension)142 {143 string ct = string.Empty;144 switch (extension.ToLower())145 {146 case ".jpg":147 ct = "image/jpeg";148 break;149 case ".png":150 ct = "image/png";151 break;152 case ".gif":153 ct = "image/gif";154 break;155 case ".bmp":156 ct = "application/x-bmp";157 break;158 default:159 ct = "image/jpeg";160 break;161 }162 return ct;163 }164 165 //获得包含有关内置图像编码解码器的信息的ImageCodecInfo 对象.166 private ImageCodecInfo GetImageCodecInfo(string contentType)167 {168 ImageCodecInfo[] arrayICI = ImageCodecInfo.GetImageEncoders();169 ImageCodecInfo jpegICI = null;170 for (int x = 0; x < arrayICI.Length; x++)171 {172 if (arrayICI[x].MimeType.Equals(contentType))173 {174 jpegICI = arrayICI[x];175 //设置JPEG编码176 break;177 }178 }179 return jpegICI;180 }181 182 public bool IsReusable183 {184 get185 {186 return false;187 }188 }189 }190 }

   图片压缩算法中,有几个参数可以根据自己的需求进行调整,比如:SmoothingMode、InterpolationMode、Encoder.Quality,反正图片的大小与图片质量成正比,也跟性能成反比,具体参数用法,请移步MSDN查看,因此大家根据实际需求进行取舍了。

  在页面需要调用地方,将img的src设置为ResizeImage.ashx,这跟图片验证码处理方式一样,如:

  1 <img runat="server" src="~/ResizeImage.ashx?src=/Upload/20140428/www_ideek_cn.jpg&width=128&height=128" /> 

  这样,一张图片可以在网站任意地方使用,图片经过压缩后传输,通过Google或Firefox浏览器开发者工具可以很明显地看出图片大小效果和加载速度都有非常明显的提升。

  当然,可能很多人会问频繁的计算对服务器会产生性能影响,所以在实际使用过程中,可以根据自己的需求采用一些手段进行规避,比如引入缓存机制等,这些优化将会在后续文章中讲解。

转载地址:http://hohlo.baihongyu.com/

你可能感兴趣的文章
项目UML设计(团队)
查看>>
Divideing Jewels
查看>>
Oulipo (poj3461
查看>>
无法建立目录wp-content/uploads/xxxx/xx。有没有上级目录的写权限?解决办法
查看>>
poj 3037 Skiing
查看>>
BZOJ 2049 洞穴勘测
查看>>
洛谷P4169 天使玩偶 (算竞进阶习题)
查看>>
11周
查看>>
Order By操作
查看>>
东北证券——“智能报表系统”的建设经验
查看>>
十分钟理解Gradle
查看>>
Mysql复习大全(转)
查看>>
回到上次目录、历史命令查找快捷方式及执行时间显示设置、查看系统版本
查看>>
略论软件模块的加载策略
查看>>
在深谈TCP/IP三步握手&四步挥手原理及衍生问题—长文解剖IP
查看>>
siege 输出结果 理解
查看>>
C语言学习趣事_20_Assert_Setjmp
查看>>
Cogs 1672. [SPOJ375 QTREE]难存的情缘 LCT,树链剖分,填坑计划
查看>>
同一个工程下使用多个.C文件的设计(模块化设计)
查看>>
java贪吃蛇
查看>>