asp.net 动态压缩、切割图片,并做缓存处理机制

在asp.net中,新建一个handler,把需要切割的网内图片,通过调用此URL来切割并缓存。http://localhost:53829/CacheImage/ResizeImage.ashx?src=/Image/FolderLevel1\FolderLevel11\FolderLevel111/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>

  

 

posted on 2015-11-20 12:59  两轮明月  阅读(809)  评论(0编辑  收藏  举报

导航