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.pswp.cn/news/458700.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/458700.shtml
英文地址,請注明出處:http://en.pswp.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、不允許重復定義的是局部變…