黃忠成

風雪之閣- i live,so i writing
文章數 - 133, 回應數 - 125, 引用數 - 0


關於我:



黃忠成

  • 資深.NET 技術顧問
  • Run! PC 雜誌專欄作者
  • 程序員雜誌文章作者
  • PC Magazine 雜誌專欄作者
  • MSDN 專欄作者
  • MSDN 特約專屬講師
  • Microsoft .NET專屬講師
  • 台灣微軟特約技術顧問
  • 台灣微軟最有價值專家


  • 批評,指教,鼓勵, 請 寫信給我
    轉載文章請使用連結模式,
    請勿整篇Copy! 謝謝!


    我所提供的教育訓練:

    Windows Forms
    ASP.NET 2.0
    如有課程需要,請與我聯絡!

  • 我的著作:

  • 文章標籤

    全部標籤

    每月文章

    文章分類

    [IE8]運用Data URI技術加快網頁載入速度

     

    運用Data URI技術加快網頁載入速度
     
     
    /黃忠成
     
     
    如何加快網頁載入速度
     
        加快網頁載入速度的方法有很多,從壓縮JavaScript到壓縮HTML都是方法之一,在Internet Explorer 8中,除了以上這兩種方法外,我們還可以透過Data URI技術來達到加快網頁載入速度的目的。
    Data URI技術,簡而言之就是把原本需要額外連線下載的資源,例如圖形檔、Object Data等資源,一併結合在HTML中下載。舉個例來說,當我們有一個網頁,裡面以數十個<img>方式連結了圖形,
    對於瀏覽器而言,它會先載入HTML,然後一一解析<img> Tag,然後一一照其src指定的URL下載圖形,這原本是很常見且很直覺的處理方式,但是這種方式對於網頁效能而言,會造成不小的影響,
    因為每一次解析<img>後,瀏覽器就會發出一次連線需求來下載圖形,當有數十個<img>時,自然會在繪製網頁期間發出相等的連線要求,加上瀏覽器多半有著最大同時連線數(大概是2個)的限制,
    所以這種傳統模式自然對於網頁載入速度上產生影響。
     
        Data URI技術就是為了解決此問題而來,我們可以在<img>的src屬性中直接以base64編碼方式,將圖形的2進位碼硬嵌入HTML中,這樣瀏覽器在繪製該<img>時,省卻了一個連線數及圖形下載量,
    網頁載入速度自然會有所提升。下面是一個Data URI應用例子:
    <html>
    <head>
    <title>Show Data URI in the IMAGE tag</title>
    <meta http-equiv="X-UA-Compatible" content="IE=7">
    </head>
    <body>
    Draws a small red square.
    <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAIAAAFSDNYfAAAAaklEQVR42u3XQQrAIAwAQeP%2F%2F6wf8CJBJTK9lnQ7FpHGaOurt1I34nfH9pMMZAZ8BwMGEvvh%2BBsJCAgICLwIOA8EBAQEBAQEBAQEBK79H5RfIQAAAAAAAAAAAAAAAAAAAAAAAAAAAID%2FABMSqAfj%2FsLmvAAAAABJRU5ErkJggg%3D%3D">fallback</img>
    </body>
    </html>
    當然,這種技術也不是全然無缺點,由於使用了內嵌的模式,瀏覽器原本對於網頁圖形的快取功能會失效,以一般的網頁及使用Data URI 的網頁來對比,
    在使用者第一次造訪時會發現Data URI的網頁比較快,但在第二次造訪時,由於沒有快取機制存在,所以傳統未使用Data URI的網頁載入速度會比使用
    Data URI的網頁快上許多(因為不用再下載圖形)。
    那除了<img>外,Data URI還可以用在那呢?就目前最常用的情況來說,Data URI技術可以應用在<img>及<object>兩個Tag中,但是由於Internet Explorer 8
    對於Data URI的內嵌內容大小限制在32K,而32K對於<object> tag來說實在太小了,因此真正實用的就只是<img>而已。
     
     
    ASP.NET DataURIImage Server Control
     
     由於一般很少用到Data URI,加上Internet Explorer直到8.0後對於Data URI的支援才完整一些,因次假設你是使用ASP.NET撰寫程式,那麼要使用Data URI來顯示圖形,你就得在程式中讀取圖形檔,
    然後轉換為Base64後設給Image控制項的ImageUrl屬性。
     為了讓讀者們能更方便的使用Data URI來顯示圖形,我特別開發了一個DataURIImage控制項,她的用法與Image控制項完全相同,不同的是其在輸出時會以Base64將圖形檔內嵌至HTML中,
    以下是該控制項的原始碼。
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Text;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.IO;
     
    namespace DataUriImage
    {
        [DefaultProperty("Text")]
        [ToolboxData("<{0}:DataUriImage runat=server></{0}:DataUriImage>")]
        public class DataUriImage : WebControl
        {
     
            public string ImageUrl
            {
                get
                {
                    object o = ViewState["ImageUrl"];
                    if (o == null)
                        return string.Empty;
                    return (string)o;
                }
                set
                {
                    ViewState["ImageUrl"] = value;
                }
            }
     
            public ImageAlign ImageAlign
            {
                get
                {
                    object o = ViewState["ImageAlign"];
                    if (o == null)
                        return ImageAlign.NotSet;
                    return (ImageAlign)o;
                }
                set
                {
                    ViewState["ImageAlign"] = value;
                }
            }
     
     
            public string AlternateText
            {
                get
                {
                    object o = ViewState["AlternateText"];
                    if (o == null)
                        return string.Empty;
                    return (string)o;
                }
                set
                {
                    ViewState["AlternateText"] = value;
                }
            }
     
            public string DescriptionUrl
            {
                get
                {
                    object o = ViewState["DescriptionUrl"];
                    if (o == null)
                        return string.Empty;
                    return (string)o;
                }
                set
                {
                    ViewState["DescriptionUrl"] = value;
                }
            }
     
            [Browsable(false)]
            public override bool Enabled
            {
                get
                {
                    return base.Enabled;
                }
                set
                {
                    base.Enabled = value;
                }
            }
     
           [Browsable(false)]
            public override FontInfo Font
            {
                get
                {
                    return base.Font;
                }
            }
     
            protected override HtmlTextWriterTag TagKey
            {
                get
                {
                    return HtmlTextWriterTag.Img;
                }
            }
     
            protected override void AddAttributesToRender(HtmlTextWriter writer)
            {
                string data;
                base.AddAttributesToRender(writer);
                if (Page.Request.Browser.Browser.Contains("IE") &&
                    Convert.ToDouble(Page.Request.Browser.Version) >= 8)
                {
                    using (FileStream fs =
                      new FileStream(HttpContext.Current.Request.MapPath(ImageUrl),
                      FileMode.Open, FileAccess.Read))
                    {
                        byte[] buff = new byte[32768];
     
                        using (BinaryReader br = new BinaryReader(fs))
                        {
                            int size = br.Read(buff, 0, 32768);
                            MemoryStream ms = new MemoryStream();
                            try
                            {
                                ms.Write(buff, 0, size);
                                data = Convert.ToBase64String(ms.GetBuffer());
                                if (data.Length > 32768)
                                    throw new Exception(
                                      "image is too large to embed as Data Uri.");
                            }
                            finally
                            {
                                ms.Dispose();
                            }
                        }
     
                    }
     
                    if (ImageUrl.EndsWith(".bmp"))
                        writer.AddAttribute(HtmlTextWriterAttribute.Src,
                                     "data:image/bmp;base64, " + data);
                    else if (ImageUrl.EndsWith(".jpg"))
                        writer.AddAttribute(HtmlTextWriterAttribute.Src,
                                     "data:image/jpg;base64, " + data);
                    else if (ImageUrl.EndsWith(".png"))
                        writer.AddAttribute(HtmlTextWriterAttribute.Src,
                            "data:image/png;base64, " + data);
                    else if (ImageUrl.EndsWith(".gif"))
                        writer.AddAttribute(HtmlTextWriterAttribute.Src,
                           "data:image/gif;base64, " + data);
                    else
                        throw new Exception("image not support.");
                }
                else
                    writer.AddAttribute(HtmlTextWriterAttribute.Src,
                         ResolveClientUrl(ImageUrl));
                if (ImageAlign != ImageAlign.NotSet)
                    writer.AddAttribute(HtmlTextWriterAttribute.Align,
                        ImageAlign.ToString().ToLower());
                if (AlternateText.Length > 0)
                    writer.AddAttribute(HtmlTextWriterAttribute.Alt, AlternateText);
                if (DescriptionUrl.Length > 0)
                    writer.AddAttribute(HtmlTextWriterAttribute.Longdesc,
                      ResolveClientUrl(DescriptionUrl));
            }
        }
    }
    安裝此控制項的方式很簡單,請下載文後範例檔案,裡面有一個DataURIImage目錄,開啟Visual Studio 2008後,開啟一個新的ASP.NET專案,接著在工具列上新增一個Ext的頁籤,
    然後按滑鼠右鍵來新增控制項。
    接著選擇DataURIImage這個Assembly
    按下開啟然後再按下確定按紐後,DataURIImage控制項就安裝在你的Visual Studio 2008中了,下面是使用DataURIImage控制項的例子。

     

    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication1._Default" %>
     
    <%@ Register Assembly="DataUriImage" Namespace="DataUriImage" TagPrefix="cc1" %>
     
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
     
    <html xmlns="http://www.w3.org/1999/xhtml" >
    <head runat="server">
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
        <div>
            <cc1:DataUriImage ID="DataUriImage1" runat="server"
                ImageUrl="~/up_green24_d.bmp" AlternateText="TEST"   Width="24px" />
        </div>
        </form>
    </body>
    </html>
    執行時,你應可於IE8上看到圖形,當使用View Source(查看原始碼)時,你會發現Data URI的蹤跡。
     
     
    後記
     
        就個人觀點而言,Data URI應是網頁調校中的最後手段,除非網頁上真的使用了很多小圖形,否則使用Data URI
    所能獲淂的增加效能其實很有限。
     
    範例下載

    posted on 2009/5/9 17:32 | 我要推薦 | 閱讀數 : 3016 | 文章分類 [ ASP.NET IE ] 訂閱

    Feedback

    目前沒有回應.

    回應

    標題
    姓名
    電子郵件 (將不會被顯示)
    個人網頁
    內容 
      登入後使用進階評論  
    Please add 2 and 4 and type the answer here:

    Powered by: