回到目錄
說在前
對于資源清單頁來說,我們經常會把圖像做成N多種,大圖,小圖,中圖等等,很是麻煩,在資料遷移時,更是一種痛快,而如果你把圖像資源部署到nginx上,那麼這種圖像縮放就變得很容易了,因為它有自己的過濾器來實作這個功能,隻要程式員簡單的配置即可(GraphicsMagick),其實在nginx上實作縮略圖的方式有很多,而對于IIS服務來說,實作這種縮略圖就沒有直接的方法了,必須開發人員自己寫代碼來實作,下面解釋兩個比較早的技術(被執行的期間比較早,在頁面渲染之前)HttpModule和httpHandler,這兩個東西我在之前的文章中也已經講過,細節不再重複。[HttpModule幾大事件,HttpHandler實作圖像防盜鍊]
做在後
一 HttpModule對URL位址進行重寫,将擴充名為jpg,jpeg,png,gif結尾的URL位址進行複寫,讓它支援漂亮的縮略圖參數,如原位址為:new1.jpg,實作縮略圖原位址為:new1.jpg?w=100&h=100,進行Url重寫後的漂亮位址為:new1_100x100.jpg,怎麼樣,是否是很漂亮,有點像MVC 的router吧,呵呵
/// <summary>
/// 實作URL的重寫
/// </summary>
public class UrlRewriteModule : IHttpModule
{
#region IHttpModule 成員
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(Application_BeginRequest);
}
/// <summary>
/// url重寫
/// .png?w=100&h=100
/// _100x100.png
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Application_BeginRequest(Object sender, EventArgs e)
{
string oldUrl = HttpContext.Current.Request.RawUrl;
if (oldUrl.LastIndexOf(".") > -1)
{
string ext = oldUrl.Substring(oldUrl.LastIndexOf(".")).ToLower();
//是圖像檔案
if (ext == ".jpg"
||
ext == ".jpeg"
||
ext == ".png"
||
ext == "gif")
{
var param = oldUrl.Substring(oldUrl.LastIndexOf("_") + 1, (oldUrl.IndexOf(".") - oldUrl.LastIndexOf("_") - 1)).Split(new char[] { 'x' }, StringSplitOptions.RemoveEmptyEntries);
//有圖像縮放請求
if (oldUrl.LastIndexOf("_") > -1)
{
string newUrl = oldUrl.Substring(0, oldUrl.LastIndexOf("_"));
newUrl = string.Format(newUrl + ext + "?w={0}&h={1}", param[0], param[1]);
//将請求中的URL進行重寫
HttpContext.Current.RewritePath(newUrl);
}
}
}
}
#endregion
#region IHttpModule 成員
public void Dispose()
{
}
#endregion
}
二 使用HttpHandler進行對圖像的縮放,你的伺服器是指與圖像資源在一起的那台電腦
/// <summary>
/// 圖檔動态縮放處理程式
/// </summary>
public class ImageScalingHandler : IHttpHandler
{
/// <summary>
/// 圖像等比例縮放,圖像預設為白色
/// </summary>
/// <param name="image"></param>
/// <param name="width"></param>
/// <param name="height"></param>
/// <returns></returns>
private Bitmap CreateThumbnail(Image image, int width, int height)
{
Point point = new Point(0, 0); //圖像從那個坐标點進行截取
double wRate = 1, hRate = 1, setRate = 1;
int newWidth = 0, newHeight = 0;
try
{
if (width == 0) width = image.Width;
if (height == 0) height = image.Height;
if (image.Height > height)
{
hRate = (double)height / image.Height;
}
if (image.Width > width)
{
wRate = (double)width / image.Width;
}
if (wRate != 1 || hRate != 1)
{
if (wRate > hRate)
{
setRate = hRate;
}
else
{
setRate = wRate;
}
}
newWidth = (int)(image.Width * setRate);
newHeight = (int)(image.Height * setRate);
if (height > newHeight)
{
point.Y = Convert.ToInt32(height / 2 - newHeight / 2);
}
if (width > newWidth)
{
point.X = Convert.ToInt32(width / 2 - newWidth / 2);
}
Bitmap bit = new Bitmap(width, height);
Rectangle r = new Rectangle(point.X, point.Y, (int)(image.Width * setRate), (int)(image.Height * setRate));
Graphics g = Graphics.FromImage(bit);
g.Clear(Color.White);
g.DrawImage(image, r);
g.Dispose();
return bit;
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// 處理請求
/// </summary>
/// <param name="context"></param>
public void ProcessRequest(HttpContext context)
{
int w = 0, h = 0;
int.TryParse(context.Request.QueryString["w"], out w);
int.TryParse(context.Request.QueryString["h"], out h);
Image image = Image.FromFile(context.Request.PhysicalPath);
context.Response.ContentType = "image/jpeg";
Bitmap bitMap = CreateThumbnail(image, w, h);
bitMap.Save(context.Response.OutputStream, ImageFormat.Jpeg);
image.Dispose();
bitMap.Dispose();
context.Response.End();
}
public bool IsReusable
{
get { return false; }
}
}
三 最後就是在Module和Handler的入口配置的,即如何将它們加入到當然網站中,我們采用web.config配置的方法
<system.web>
<httpModules>
<!-- this is for Classic mode and Cassini -->
<add name="UrlRewriteModule" type="EntityFrameworks.Web.Core.HttpModules.UrlRewriteModule,EntityFrameworks.Web.Core" />
</httpModules>
</system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" >
<!--This is for Integrated mode-->
<add name="UrlRewriteModule" type="EntityFrameworks.Web.Core.HttpModules.UrlRewriteModule,EntityFrameworks.Web.Core" />
</modules>
<handlers>
<add name="ImageFunction1" path="*.jpg" verb="GET" type="EntityFrameworks.Web.Core.HttpHandlers.ImageScalingHandler,EntityFrameworks.Web.Core" />
<add name="ImageFunction2" path="*.png" verb="GET" type="EntityFrameworks.Web.Core.HttpHandlers.ImageScalingHandler,EntityFrameworks.Web.Core" />
<add name="ImageFunction3" path="*.gif" verb="GET" type="EntityFrameworks.Web.Core.HttpHandlers.ImageScalingHandler,EntityFrameworks.Web.Core" />
<add name="ImageFunction4" path="*.jpeg" verb="GET" type="EntityFrameworks.Web.Core.HttpHandlers.ImageScalingHandler,EntityFrameworks.Web.Core" />
</handlers>
從上面的代碼中,我們可以看到,對于modules來說,那有兩種方式注入,一為IIS經典模式下的,另一種是IIS內建模式下的,我們需要分别進行配置。
可以看一下效果,成功的喜悅!
大叔架構集又一成功元件...
作者:倉儲大叔,張占嶺,
榮譽:微軟MVP
QQ:853066980
支付寶掃一掃,為大叔打賞!
