网站性能优化:动态缩略图技术实现思路

简介:

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

  很多网站可能没有对图片进行缩略图处理,上传时图片可能几百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     /// <summary>
 12     /// 动态缩略图处理程序
 13     /// 调用示例: <img runat="server" src="~/ResizeImage.ashx?src=/Upload/20140428/www_ideek_cn.jpg&width=128&height=128" />
 14     /// </summary>
 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                 else
112                 {
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             finally
125             {
126                 if (fileStream != null)
127                 {
128                     fileStream.Close();
129                     fileStream.Dispose();
130                 }
131             }
132             System.GC.Collect();
133         }
134 
135 
136         /// <summary>
137         /// 获取文件下载类型
138         /// </summary>
139         /// <param name="extension"></param>
140         /// <returns></returns>
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 IsReusable
183         {
184             get
185             {
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浏览器开发者工具可以很明显地看出图片大小效果和加载速度都有非常明显的提升。

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

分类:  ASP.NET
本文转自左正博客园博客,原文链接:http://www.cnblogs.com/soundcode/p/4648346.html ,如需转载请自行联系原作者
相关文章
|
1月前
|
缓存 前端开发 JavaScript
绝了!前端优化新高度,教你如何让你的网站加载速度比火箭还快!
本文介绍了多种前端优化技术,包括文件压缩与合并、图片优化、缓存策略、服务器端渲染(SSR)和客户端渲染(CSR)的选择,以及利用CDN加速静态资源加载,帮助你显著提升网站加载速度,优化用户体验。
75 31
|
2月前
|
缓存 前端开发 UED
前端 8 种图片加载优化方案梳理
本文首发于微信公众号“前端徐徐”,详细探讨了现代网页设计中图片加载速度优化的重要性及方法。内容涵盖图片格式选择(如JPEG、PNG、WebP等)、图片压缩技术、响应式图片、延迟加载、CDN使用、缓存控制、图像裁剪与缩放、Base64编码等前端图片优化策略,旨在帮助开发者提升网页性能和用户体验。
401 0
|
4月前
|
C# UED 开发者
WPF与性能优化:掌握这些核心技巧,让你的应用从卡顿到丝滑,彻底告别延迟,实现响应速度质的飞跃——从布局到动画全面剖析与实例演示
【8月更文挑战第31天】本文通过对比优化前后的方法,详细探讨了提升WPF应用响应速度的策略。文章首先分析了常见的性能瓶颈,如复杂的XAML布局、耗时的事件处理、不当的数据绑定及繁重的动画效果。接着,通过具体示例展示了如何简化XAML结构、使用后台线程处理事件、调整数据绑定设置以及利用DirectX优化动画,从而有效提升应用性能。通过这些优化措施,WPF应用将更加流畅,用户体验也将得到显著改善。
313 1
|
4月前
PPT 做出动态路线动画
PPT 做出动态路线动画
38 0
|
7月前
|
UED
【专栏:交互与用户体验篇】网页中的色彩搭配与配色方案
【4月更文挑战第30天】网页设计中,色彩搭配影响用户体验。了解色彩心理学、搭配原则及配色方案至关重要。色彩能传达信息、影响感知,通过对比与和谐、色彩平衡和层次创造良好视觉效果。单色、类似色、对比色和互补色四种配色方案各有优缺点,需根据目标用户和网页需求选择。恰当的色彩运用能提升美感,增强网页吸引力。
159 5
|
7月前
|
前端开发 UED 开发者
【专栏】探讨了CSS3动画卡顿的原因,包括复杂动画效果、过多元素参与、低效代码结构和硬件资源限制,并提出优化措施
【4月更文挑战第29天】本文探讨了CSS3动画卡顿的原因,包括复杂动画效果、过多元素参与、低效代码结构和硬件资源限制,并提出优化措施:简化动画路径、控制元素数量、优化代码结构、利用硬件加速及性能监测。通过实际案例展示了优化效果,强调了性能优化对提升用户体验的重要性。在开发中,应持续关注并优化动画性能,以适应网页应用的需求。
411 1
|
7月前
显示广告的几种方案及缺点
显示广告的几种方案及缺点
56 0
|
7月前
|
前端开发 搜索推荐 JavaScript
探析单页应用(SPA)与多页应用(MPA):从技术角度选择合适的应用形式
随着Web应用的快速发展,单页应用(SPA)和多页应用(MPA)成为了开发者们在构建Web应用时常遇到的两种选择。本文将从技术角度出发,深入比较单页应用和多页应用的特点和优势,帮助读者更好地选择适合自己项目的应用形式。
99 0
聊天框(番外篇)—如何实现@功能的整体删除
上一篇文章中,我们已经初步实现了聊天输入框,但其@功能是不完善的,例如无法整体删除、无法获取除用户名以外的数据(假设用户名不是唯一的)。有问题就要想办法解决,在网上百度了一圈后,倒是有一些收获。本文就着重解决@的整体删除以及获取额外数据。
1138 0
聊天框(番外篇)—如何实现@功能的整体删除
|
存储 前端开发 算法
前端性能优化-图片
前端性能优化-图片
265 29
前端性能优化-图片