標籤:
Data URL 早在 1995 年就被提出,那個時候有很多個版本的 Data URL Schema 定義陸續出現在 VRML 之中,隨後不久,其中的一個版本被提上了議案——將它做個一個嵌入式的資源放置在 HTML 語言之中。從 RFC 文檔定稿的時間來看(1998年),它是一個很受歡迎的發明。
Data URIs 定義的內容可以作為小檔案被插入到其他文檔之中。URI 是 uniform resource identifier 的縮寫,它定義了接受內容的協議以及附帶的相關內容,如果附帶的相關內容是一個地址,那麼此時的 URI 也是一個 URL (uniform resource locator),如:
ftp://10.1.1.10/path/to/filename.exthttp://example.com/source/id
協議後面的內容,可以告訴用戶端一個準確下載資源的地址,而 URI 並不一定包含一個地址資訊,如(demo):
data:image/gif;base64,R0lGODlhEAAOALMAAOazToeHh0tLS/7LZv/0jvb29t/f3//Ub//ge8WSLf/rhf/3kdbW1mxsbP//mf///yH5BAAAAAAALAAAAAAQAA4AAARe8L1Ekyky67QZ1hLnjM5UUde0ECwLJoExKcppV0aCcGCmTIHEIUEqjgaORCMxIC6e0CcguWw6aFjsVMkkIr7g77ZKPJjPZqIyd7sJAgVGoEGv2xsBxqNgYPj/gAwXEQA7
其協議為 data,並告訴用戶端將這個內容作為 image/gif 格式來解析,需要解析的內容使用的是 base64 編碼。它直接包含了內容但並沒有一個確定的資源地址。
? 格式
Data URI 的格式十分簡單,如下所示:
data:[<mime type>][;charset=<charset>][;base64],<encoded data>
第一部分是 data: 協議頭,它標識這個內容為一個 data URI 資源。
第二部分是 MIME 類型,表示這串內容的展現方式,比如:text/plain,則以文本類型展示,image/jpeg,以 jpeg 圖片形式展示,同樣,用戶端也會以這個 MIME 類型來解析資料。
第三部分是編碼設定,預設編碼是 charset=US-ASCII, 即資料部分的每個字元都會自動編碼為 %xx,關於編碼的測試,可以在瀏覽器地址框輸入分別輸入下面兩串內容,查看效果:
// output: ä½ å¥½ -> 使用預設的編碼展示,故亂碼data:text/html,你好 // output: 你好 -> 使用 UTF-8 展示data:text/html;charset=UTF-8,你好 // output: 浣犲ソ -> 使用 gbk 展示(瀏覽器預設編碼 UTF-8,故亂碼)data:text/html;charset=gbk,你好 // output: 你好 -> UTF-8 編碼,內容先使用 base64 解碼,然後展示data:text/html;charset=UTF-8;base64,5L2g5aW9
第四部分是 base64 編碼設定,這是一個可選項,base64 編碼中僅包含 0-9,a-z,A-Z,+,/,=,其中 = 是用來編碼補白的。
最後一部分為這個 Data URI 承載的內容,它可以是純文字編寫的內容,也可以是經過 base64編碼 的內容。
很多時候我們使用 data URI 來呈現一些較長的內容,如一串位元據編碼、圖片等,採用 base64 編碼可以讓內容變得更加簡短。而對圖片來說,在 gzip 壓縮之後,base64 圖片實際上比原圖 gzip 壓縮要大,體積增加大約為三分之一,所以使用的時候需要權衡。
? 相容性
由於出現時間較早,目前主流的瀏覽器基本都支援 data URI:
- Firefox 2+
- Opera 7.2+
- Chrome (所有版本)
- Safari (所有版本)
- Internet Explorer 8+
但是部分瀏覽器對 data URI 的使用存在限制:
長度限制,長度超長,在一些應用下會導致記憶體溢出,程式崩潰
Opera 下限制為 4100 個字元,目前已經去掉了這個限制IE 8+ 下限制為 32,768 個字元(32kb),IE9 之後移除了這個限制
在 IE 下,data URI 只允許被用到如下地方:
- object (images only)
- img、input type=image、link
- CSS 中允許使用 URL 聲明的地方,如 background
- 在 IE 下,Data URI 的內容必須是經過編碼轉換的,如 “#”、”%”、非 US-ASCII 字元、多位元組字元等,必須經過編碼轉換
? 低版本IE的解決之道 - MHTML
MHTML 就是 MIME HTML,是 “Multipurpose Internet Mail Extensions HyperText Markup Language” 的簡稱,它就像一個帶著附件的郵件一般,如下所示:
/** FilePath: http://example.com/test.css *//*[email protected]Content-Type: multipart/related; boundary="_ANY_SEPARATOR"--_ANY_SEPARATORContent-Location:myidBackgroundContent-Transfer-Encoding:base64iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==--_ANY_SEPARATOR--*/.myid { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="); *background-image: url(mhtml:http://example.com/test.css!myidBackground); }
上方的一串注釋就像是一個附件,這個附件內容是一個名叫 myidBackground 的 base64 編碼圖片,在一個 class 叫做 myid 的 css 中用到了它。這裡有幾點需要注意:
_ANY_SEPARATOR 可以是任意內容
- 在”附件”結束位置需要加上結束符
_ANY_SEPARATOR,否則在 Vista 和 Win7 的 IE7 中會出錯。
- 附件代碼注意不要被壓縮公用程式給幹掉了
這裡存在一個坑:部分系統相容模式下的 IE8 也認識 css 中的 hack 符號 *,但是不支援 mhtml,所以上面的內容不會生效。處理方案估計就只有使用 IE 的條件注釋了。
? HTTPS 下的安全提示
HTTPS 開啟頁面,當在 IE6、7 下使用 data URIs 時,會看到如下提醒:
MS 的解釋是:
您正在查看的網站是個安全網站。它使用了 SSL (安全通訊端層)或 PCT(保密通訊技術)這樣的安全性通訊協定來確保您所收發資訊的安全性。 當網站使用安全性通訊協定時,您提供的資訊例如姓名或信用卡號碼等都經過加密,其他人無法讀取。然而,這個網頁同時包含未使用該安全性通訊協定的項目。
很明顯,IE 嗅到了”未使用安全性通訊協定的項目”。
瀏覽器在解析到一個 URI 的時候,會首先判斷協議頭,如果是以 http(s) 開頭,它便會建立一個網路連結下載資源,如果它發現協議頭為 data:,便會將其作為一個 Data URI 資源進行解析。
但是從 chrome 的瀑布流,我們可以做這樣的猜測:
圖中每個 Data URI 都發起了請求,不過狀態都是 data(from cache),禁用緩衝之後,依然如此。所以可以斷定,瀏覽器在下載源碼解析成 DOM 的時候,會將 Data URI 的資源解析出來,並緩衝在本地,最後 Data URI 每個對應位置都會發起一次請求,只是這個請求還未建立連結,就被發現存在緩衝的瀏覽器給拍死了。
? 安全閥門
Data URI 在 IE 下有諸多安全限制,事實上,很多 xss 注入也可以將 data URI 的源頭作為入口,使用 data URI 繞過瀏覽器的過濾。
// 繞過瀏覽器過濾http://example.com/text.php?t="><script src="data:text/html,<script>alert("Xss")</script><!--
這裡可以很大程度的發散,很有意思,值得讀者去深究。
? 擴充閱讀
- RFC 2397 RFC文檔
- MDN - data_URIs MDN文檔
- MSDN - data Protocal MSDN文檔
- NC - data_uris_explained
- phpied - MHTML
http://www.cnblogs.com/hustskyking/p/data-uri.html
Data URI(轉)