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


    在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>
    

      

  • 相关阅读:
    java关键字synchronized
    JVM调优之jstack找出最耗cpu的线程并定位代码
    高性能Mysql
    awk使用入门
    JVM性能调优监控工具
    java垃圾回收算法
    JVM内存模型
    jvm之内存分配与回收策略
    leetcode 78. 子集(c++)
    leetcode 148. 排序链表(c++)
  • 原文地址:https://www.cnblogs.com/zhengshuangliang/p/4980399.html
Copyright © 2020-2023  润新知