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", ".jpegextensionContentTypeDic = 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 实现。

转载于:https://www.cnblogs.com/straw/p/5459473.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/458700.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据库事务的隔离机制

数据库事务(Database Transaction) &#xff0c;是指作为单个逻辑工作单元执行的一系列操作&#xff0c;要么完全地执行&#xff0c;要么完全地不执行。----百度百科就是说你定义一组数据库操作&#xff0c;然后告诉数据库说这些操作要么都成功&#xff0c;要么都不成功。类似于…

如何使用CppUnit进行单元测试

http://www.vckbase.com/document/viewdoc/?id1762 一、前言 测试驱动开发(TDD)是以测试作为开发过程的中心&#xff0c;它坚持&#xff0c;在编写实际代码之前&#xff0c;先写好基于产品代码的测试代码。开发过程的目标就是首先使测试能够通过&#xff0c;然后再优化设计结构…

录制wav格式的音频

项目中有面部认证、声纹认证&#xff0c;服务器端要求上传wav格式的音频&#xff0c;所以写了这样一个小demo。 刚刚开始写博客还不知道怎么上传代码&#xff0c;就复制了&#xff0c;嘻嘻 DotimeManage.h class DotimeManage; protocol DotimeManageDelegate <NSObject&g…

iOS开发网络篇—Reachability检测网络状态

前言&#xff1a;当应用程序需要访问网络的时候&#xff0c;它首先应该检查设备的网络状态&#xff0c;确认设备的网络环境及连接情况&#xff0c;并针对这些情况提醒用户做出相应的处理。最好能监听设备的网络状态的改变&#xff0c;当设备网络状态连接、断开时&#xff0c;程…

网络七层协议 五层模型 TCP连接 HTTP连接 socket套接字

socket&#xff08;套接字&#xff09;是通信的基石&#xff0c;是支持TCP/IP协议的网络通信的基本操作单元&#xff0c;包含进行网络通信必须的五种信息&#xff1a;连接使用的协议&#xff0c;本地主机的IP地址&#xff0c;本地进程的协议端口&#xff0c;远地主机的IP地址&a…

[vs2010 project] CppUnit快速入门

简介 测试是软件开发过程中极其重要的一环&#xff0c;详尽周密的测试能够减少软件BUG&#xff0c;提高软件品质。测试包括单元测试、系统测试等。其中单元测试是指针对软件功能单元所作的测试&#xff0c;这里的功能单元可以是一个类的属性或者方法&#xff0c;测试的目的是看…

[javascript|基本概念|Number]学习笔记

Number类型的值&#xff1a;整数/浮点数值 整数 十进制 e.g.: var intNum 50; 八进制 (严格模式下无效,解析错误)字面值首位必须是0,之后的数字序列为0&#xff5e;7 e.g.: var intNum 070; //解析为十进制56 (如果字面值数值超出了范围&#xff0c;前导0将被忽略&#xf…

[转]深入理解linux内核list_head

http://blog.chinaunix.net/uid-27122224-id-3277511.html 深入理解linux内核list_head的实现 2012-07-17 17:37:01 分类&#xff1a; LINUX 前言&#xff1a;在linux源代码中有个头文件为list.h。很多linux下的源代码都会使用这个头文件&#xff0c;它里面定义 了一个结构,以及…

xcode左侧不显示工程文件目录,提示NO Filter Results

解决办法&#xff1a; What solved was to go to Navigate > Reveal in Project Navigator . After this, the structure appeared again.

【VC++技术杂谈005】如何与程控仪器通过GPIB接口进行通信

在工控测试系统中&#xff0c;经常需要使用到各类程控仪器&#xff0c;这些程控仪器通常具有GPIB、LAN、USB等硬件接口&#xff0c;计算机通过这些接口能够与其通信&#xff0c;从而实现自动测量、数据采集、数据分析和数据处理等操作。本文主要介绍如何与程控仪器通过GPIB接口…

标题在上边框中的html(fieldset标签)

<fieldset> <legend>标题</legend> 内容 </fieldset> 转载于:https://www.cnblogs.com/lswbk/p/4952820.html

移除项目中的CocoaPods

在项目中移除CocoaPods cocoaPods虽然很方便&#xff0c;但是我是真心的不喜欢用它&#xff0c;总是出错如果你觉得CocoaPods让你的项目出现了问题&#xff0c;不好用甚至是恶心&#xff0c;想将其从项目中彻底移除&#xff0c;也有方法&#xff1a; 1.删除工程文件夹下的Podf…

ShellExecute使用详解

有三个API函数可以运行可执行文件WinExec、ShellExecute和CreateProcess。 1.CreateProcess因为使用复杂&#xff0c;比较少用。 2.WinExec主要运行EXE文件。如&#xff1a;WinExec(Notepad.exe Readme.txt, SW_SHOW); 3.ShellExecute不仅可以运行EXE文件&#xff0c;也可以运行…

javascript笔记整理(对象基础)

一、名词解释 1.基于对象&#xff08;一切皆对象&#xff0c;以对象的概念来编程&#xff09; 2.面向对象编程(Object Oriented Programming&#xff0c;OOP) A.对象(JavaScript 中的所有事物都是对象) B.对象的属性和行为 属性:用数据值来描述他的状态 行为:用来改变对象行为的…

java的安装和配置

JRE (JAVA Runtime Enviroment java运行环境),包括JVM(java虚拟机)和java程序所需的核心功能类库&#xff0c;如果只是运行java程序&#xff0c;只需安装JRE。 JDK &#xff08;Java Development Kit 开发工具包&#xff09;包括开发JAVA程序时所需的工具&#xff0c;包括JRE…

#if, #ifdef, #ifndef, #else, #elif, #endif的用法

#ifdef的用法 灵活使用#ifdef指示符&#xff0c;我们可以区隔一些与特定头文件、程序库和其他文件版本有关的代码。 代码举例&#xff1a;新建define.cpp文件 &#xff03;include "iostream.h" int main() { #ifdef DEBUG cout<< "Beginning ex…

redhat 6.6 安装 (LVM)

http://www.cnblogs.com/kerrycode/p/4341960.html转载于:https://www.cnblogs.com/zengkefu/p/4954955.html

MFC对话框最小化到托盘

1、在资源中的Icon中导入一个自己喜欢的图标&#xff0c;ID命名为IDR_MAINFRAME&#xff0c;将先前的IDR_MAINFRAME的图标删除掉&#xff1b; 2、在自己的Dialog头文件中定义一个变量 NOTIFYICONDATA m_nid&#xff0c;关于该结构体的具体信息可以查阅MSDN&#xff1b; 3、添加…

Android acache读后感

今天了解到了一个android轻量级的开源缓存框架,(github&#xff1a;https://github.com/yangfuhai/ASimpleCache),花了一点时间研究了一下源代码&#xff0c;大概的思路就是每个缓存目录对应一个Acache类&#xff0c;通过mInstanceMap关联&#xff08;个人觉得这个主要是减少对…

continue break

块作用域 一个块或复合语句是用一对花括号&#xff08;"{}"&#xff09;括起来的任意数量的简单的java语句。块定义了变量的作用范围。 1、嵌套块是方法内的嵌套&#xff0c;不包括类的花括号。在嵌套块内的 变量是不可以重复定义的。 2、不允许重复定义的是局部变…