zoukankan      html  css  js  c++  java
  • Asp.net mvc 实时生成缩率图到硬盘

    之前对于缩率图的处理是在图片上传到服务器之后,同步生成两张不同尺寸的缩率供前端调用,刚开始还能满足需求,慢慢的随着前端展示的多样化,缩率图已不能前端展示的需求,所以考虑做一个实时生成图片缩率图服务。

    每次调用实时生成缩率图,不缓存着实有点浪费,所以在生成缩率的同时缓存到硬盘一份,效率提高很多。

    之前从网上看了一下有人用nginx + lua实现的,效率那是没什么可说的,但是时间紧迫,自己也没时间去研究,所以暂时先用aps.net mvc4来实现 一个,以后有时间了,再慢慢修改。

    用自己熟悉的.net性能可能差那么一点点,但是实现速度快,保证可以在极端的时间内上线,并且在功能上更强。

    思路很简单,就是根据请求,判断需要的缩率图是否已存在于硬盘上,如果有直接返回,没有则下载原图,并生成缩率图到本地,返回给客户端。

    下面直接粘贴代码片段:

    /// <summary>
            /// 生成图片缩率图Action
            /// </summary>
            /// <param name="p">原图url</param>
            /// <param name="id">图片尺寸以及生成缩率图的类型</param>
            /// <returns></returns>
            [HttpGet]
            public async Task<ActionResult> Index(string p, string id)
            {
                if (string.IsNullOrEmpty(p))
                {
                    return new HttpStatusCodeResult(404);
                }
    
                string oPath = Regex.Replace(p, @"http[s]?://(.*?)/", "/", RegexOptions.IgnoreCase);
                int? oWidth = 200, oHeight = 200;
                int cutMode = 3;
                string pPath;
                string oDir;
    
                if (!string.IsNullOrEmpty(id))
                {
                    string[] ss = id.Split(new char[] { '_' }, StringSplitOptions.RemoveEmptyEntries);
                    if (ss.Length < 2)
                    {
                        return new HttpStatusCodeResult(404);
                    }
                    if (ss.Length > 2)
                    {
                        cutMode = int.Parse(ss[2]);
                    }
                    oPath = oPath.Insert(oPath.LastIndexOf('/') + 1, string.Format("{0}_{1}_{2}_", ss[0], ss[1], cutMode));
                    oWidth = int.Parse(ss[0]);
                    oHeight = int.Parse(ss[1]);
                }
    
                pPath = Server.MapPath(oPath);
                oDir = Path.GetDirectoryName(pPath);
    
                if (!System.IO.File.Exists(pPath))
                {
                    byte[] imagebytes =await FileHelper.DownLoadFileAsync(p);
                    if (!Directory.Exists(oDir))
                    {
                        Directory.CreateDirectory(oDir);
                    }
                    FileHelper.MakeThumbnail(FileHelper.BytToImg(imagebytes), oWidth.Value, oHeight.Value, (ThumbnailMode)cutMode, pPath, true);
                }
    
                return File(pPath, FileHelper.GetContentTypeByExtension(Path.GetExtension(pPath).ToLower()));
            }

    辅助方法:

     public class FileHelper
        {
             /// <summary>
            /// 图片后缀和ContentType对应字典
            /// </summary>
            static Dictionary<string, string> extensionContentTypeDic;
    
            static FileHelper()
            {
                if (extensionContentTypeDic == null)
                {
                    //.jpg", ".png", ".gif", ".jpeg
                    extensionContentTypeDic = new Dictionary<string, string>();
                    extensionContentTypeDic.Add(".jpg", "image/jpeg");
                    extensionContentTypeDic.Add(".png", "image/png");
                    extensionContentTypeDic.Add(".gif", "image/gif");
                    extensionContentTypeDic.Add(".jpeg", "image/jpeg");
                }
            }
            /// <summary>
            /// 根据后缀名获取extension
            /// </summary>
            /// <param name="extension"></param>
            /// <returns></returns>
            public static string GetContentTypeByExtension(string extension)
            {
                if (extensionContentTypeDic.ContainsKey(extension))
                {
                    return extensionContentTypeDic[extension];
                }
                return null;
            }
    
            ///  <summary > 
            /// 将Image对象转化成二进制流 
            ///  </summary > 
            ///  <param name="image" > </param > 
            ///  <returns > </returns > 
            public static byte[] ImageToByteArray(Image image)
            {
                MemoryStream imageStream = new MemoryStream();
                Bitmap bmp = new Bitmap(image.Width, image.Height);
                Graphics g = Graphics.FromImage(bmp);
                g.DrawImage(image, new System.Drawing.Rectangle(0, 0, image.Width, image.Height));
                try
                {
                    bmp.Save(imageStream, image.RawFormat);
                }
                catch (Exception e)
                {
    
                    bmp.Save(imageStream, System.Drawing.Imaging.ImageFormat.Jpeg);
                }
                byte[] byteImg = imageStream.GetBuffer();
                bmp.Dispose();
                g.Dispose();
                imageStream.Close();
                return byteImg;
            }
    
            /// <summary> 
            /// 字节流转换成图片 
            /// </summary> 
            /// <param name="byt">要转换的字节流</param> 
            /// <returns>转换得到的Image对象</returns> 
            public static Image BytToImg(byte[] byt)
            {
                MemoryStream ms = new MemoryStream(byt);
                Image img = Image.FromStream(ms);
                ms.Close();
                return img;
            }
    
            /// <summary>
            /// 生成缩率图
            /// </summary>
            /// <param name="originalImage">原始图片Image</param>
            /// <param name="width">缩率图宽</param>
            /// <param name="height">缩率图高</param>
            /// <param name="mode">生成缩率图的方式</param>
            /// <param name="thumbnailPath">缩率图存放的地址</param>
            public static Image MakeThumbnail(Image originalImage, int width, int height, ThumbnailMode mode, string thumbnailPath, bool isSave = true)
            {
                int towidth = width;
                int toheight = height;
    
                int x = 0;
                int y = 0;
                int ow = originalImage.Width;
                int oh = originalImage.Height;
                switch (mode)
                {
                    case ThumbnailMode.HW://指定高宽缩放(可能变形)                  
                        break;
                    case ThumbnailMode.W://指定宽,高按比例                      
                        toheight = originalImage.Height * width / originalImage.Width;
                        break;
                    case ThumbnailMode.H://指定高,宽按比例  
                        towidth = originalImage.Width * height / originalImage.Height;
                        break;
                    case ThumbnailMode.Cut://指定高宽裁减(不变形)                  
                        if ((double)originalImage.Width / (double)originalImage.Height > (double)towidth / (double)toheight)
                        {
                            oh = originalImage.Height;
                            ow = originalImage.Height * towidth / toheight;
                            y = 0;
                            x = (originalImage.Width - ow) / 2;
                        }
                        else
                        {
                            ow = originalImage.Width;
                            oh = originalImage.Width * height / towidth;
                            x = 0;
                            y = (originalImage.Height - oh) / 2;
                        }
                        break;
    
                    default:
                        break;
                }
    
                //新建一个bmp图片  
                System.Drawing.Image bitmap = new System.Drawing.Bitmap(towidth, toheight);
                //新建一个画板  
                Graphics g = System.Drawing.Graphics.FromImage(bitmap);
                //设置高质量插值法  
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
                //设置高质量,低速度呈现平滑程度  
                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                //清空画布并以透明背景色填充  
                g.Clear(Color.Transparent);
                //在指定位置并且按指定大小绘制原图片的指定部分  
                g.DrawImage(originalImage, new Rectangle(0, 0, towidth, toheight),
                 new Rectangle(x, y, ow, oh),
                 GraphicsUnit.Pixel);
                if (!isSave)
                {
                    return bitmap;
                }
                try
                {
                    //以jpg格式保存缩略图  
                    //bitmap.Save(thumbnailPath, bitmap.RawFormat);
                    bitmap.Save(thumbnailPath, ImageFormat.Jpeg);
                    return bitmap;
    
                }
                catch (System.Exception e)
                {
                    throw e;
                }
                finally
                {
                    originalImage.Dispose();
                    bitmap.Dispose();
                    g.Dispose();
                }
                return null;
            }
    
    
            /// <summary>
            /// 下载指定文件
            /// </summary>
            /// <param name="remoteUrl"></param>
            /// <param name="ss"></param>
            public static Task<byte[]> DownLoadFileAsync(string remoteUrl)
            {
                WebClient wc = new WebClient();
                try
                {
                    return wc.DownloadDataTaskAsync(remoteUrl);
                }
                catch (Exception e)
                {
                    throw new Exception("下载文件失败");
                }
            }
    
        }
    
        public enum ThumbnailMode
        {
            /// <summary>
            /// 指定高宽缩放(可能变形)
            /// </summary>
            HW,
            /// <summary>
            /// 指定高,宽按比例
            /// </summary>
            H,
            /// <summary>
            /// 指定宽,高按比例
            /// </summary>
            W,
            /// <summary>
            /// 指定高宽裁减(不变形)   
            /// </summary>
            Cut,
    
        }

    访问方式:

    http://www.souji8.com/Home/Index/{width}_{height}_{ThumMode}?p={imageUrl}

    {imageUrl}:目标图片地址

    {ThumMode}: 1:指定高宽按比例、2:指定宽,高按比例、3:指定高宽裁减(不变形) 

    {Width}:期望图片宽

    {Height}:期望图片高

    等有时间了,再改成nginx+lua 实现。

  • 相关阅读:
    获取页面元素的xpath,验证自己写的xpath,不用工具不用插件,看完这篇保证你学会!
    Python判断IEDriverServer是否最新版本并自动更新
    Python判断软件版本号的大小
    selenium通过加载火狐Firefox配置文件FirefoxProfile,实现免登陆访问网站
    mysql查询每个学生的各科成绩,以及总分和平均分
    selenium点击(click)页面元素没有反应(报element not interactable)的一个案例
    Python查询物理主机上所有虚拟机并保存为excel,通过标记批量启动
    Python线程池下载txt
    Python自动下载最新的chromedriver
    django的url的name参数的意义
  • 原文地址:https://www.cnblogs.com/straw/p/5459473.html
Copyright © 2011-2022 走看看