淺嚐Data URI
3 |
有看過這種HTML嗎?
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Data URI</title>
<link href="data:text/css;base64,77u/aW1nICANCnsNCiAgICBib3JkZXI6IDFweCBzb2xpZCByZWQ7DQp9DQo=" rel="stylesheet" type="text/css" />
</head>
<body>
<form id="form1" runat="server">
<img src="data:image/gif;base64,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" />
</form>
</body>
</html>
在HTML裡link的href及img的src,並沒有指向某個URL,而是直接嵌入一段Base64編碼,而IE8+, Firefox, Safari, Opera, Chrome都能正確顯示其中的圖檔與CSS設定。
這種表示方法叫做data URI schema,是新一代瀏覽器支援的檔案資料表現格式,允許在網頁裡以字串形式直接內嵌圖檔、CSS檔案,進而達到以下好處:
- 瀏覽器不用為了下載圖檔、CSS另外發動HTTP Request。每次HTTP傳輸產生的額外資料量(HTTP Header、TCP/IP Header...等),累積下來多半會大於使用Base64編碼二進位資料所增加的資料量(每3個Byte增加一個Byte),事實上內嵌成Base64字串反而較節省頻寬。
- 基於TCP傳輸特性,傳送一個大檔案會比連續傳送多個拆解的小檔更快速有效率。(HTTP Keep-Alive可以改善傳送多個小檔案效率不佳的問題,但並不能徹底解決)
- 使用HTTPS(SSL)傳輸時,因為HTTPS Request的額外程序更多,內嵌資料做法的改善更明顯。
- 瀏覽器通常會有同時使用HTTP連線數的上限(例如: 兩條),將所有需要資料一次下載回來,可以避免持續佔用寶貴的連線資源。
- 以往在網頁式的Rich Text編輯器裡處理貼上圖檔,得將圖檔上傳至伺服器端某處,再將URL丟回編輯器中。使用內嵌資料寫法,可讓網頁編輯文字要內嵌圖檔容易多了。
當然,凡事不會有利無害,網頁內嵌資料的做法也有其缺點:
- 因圖檔內容被綁在網頁中,若為動態網頁每次內容都會變化,就無法透過快取加速及節省頻寬,網頁內容含圖檔資料,每次都得重新下載。
- 當檔案資料有變化時,所有內嵌它的網頁都要重新產生編碼。
- IE8以上的版本才有支援,且限制大小不可超過32KB
- Base64會讓內容變大33%,但若Web Server端啟用GZIP壓縮,增加的大小可以縮小到2-3%。
- 對資安軟體來說,Data URI增加了網頁內容檢驗的難度。
IE從IE8開始才支援這種Data URI的做法,且基於安全、效率的考量,加入了一些限制:
- 不支援Javascript檔內嵌,避免惡意程式藏匿其中,逃避Script過濾機制。
- 內嵌檔案大小不可超過32KB。
- 支援格式包含:
object
(images only) ,img,
input type=image,
link
以及CSS宣告,例如:background-image
,background
,list-style-type
,list-style等。
我寫了一小段ASP.NET程式用來產生Data URI字串,最前面的HTML就是透過這個工具做出來的,大家也可以玩看看。
using System;
using System.IO;
public partial class DataURI_Default : System.Web.UI.Page
{
private string GenDataURI(string contentType, string filePath)
{
byte[] buff = File.ReadAllBytes(filePath);
return string.Format("data:{0};base64,{1}",
contentType, Convert.ToBase64String(buff));
}
protected void Page_Load(object sender, EventArgs e)
{
string path = Request["path"] ?? "";
if (!string.IsNullOrEmpty(path) &&
File.Exists(Server.MapPath(path)))
{
string contentType = "";
switch (path.ToLower().Substring(path.Length-4, 4))
{
case ".jpg":
contentType="image/jpeg";
break;
case ".gif":
contentType="image/gif";
break;
case ".png":
contentType="image/png";
break;
case ".htm":
contentType="text/html";
break;
case ".css":
contentType="text/css";
break;
default:
Response.Write("Not supperted file type!");
Response.End();
break;
}
Response.Write(GenDataURI(contentType, Server.MapPath(path)));
Response.End();
}
}
}
Comments
# by Mesak
男丁大有寫個應用程式可以直接轉.... 這東西我也滿長拿來放進 greasemonkey http://userscripts.org/scripts/show/63761
# by player
php版的實驗版 http://www.player.idv.tw/prog/toolkits/web/data_uri.php 如果要看code的話,放在 http://www.player.idv.tw/prog/index.php/Data_URI_scheme#PHP
# by drem
發現 google搜尋結果多了圖片預覽… 再仔細一看,大神的預覽圖片是用 data URI的方式做的