【新增】:http://www.webhek.com/post/data-url.htmlphp
引子:在研究FileReader時,有個方法readAsDataURL;而後看到打印出來的東西相似於以下:【data:text/plain;base64,Y29tZSBvbiB0byBidXkgYSBwaWFubyE=】,這個東西居然像個超連接同樣能夠跳轉,在新窗口中顯示出文檔內容,若是是圖片還會顯示出圖片。因而比較好奇這是如何定位到圖片的位置的,原來這串字符並無定位圖片位置,而是將圖片的內容直接包含了進去,因此瀏覽器就直接解析出來了。具體用法見以下文章css
摘自: http://www.cnblogs.com/hustskyking/p/data-uri.htmlhtml
Data URL 早在 1995 年就被提出,那個時候有不少個版本的 Data URL Schema 定義陸續出如今 VRML 之中,隨後不久,其中的一個版本被提上了議案——將它作個一個嵌入式的資源放置在 HTML 語言之中。從 RFC 文檔定稿的時間來看(1998年),它是一個很受歡迎的發明。web
Data URIs 定義的內容能夠做爲小文件被插入到其餘文檔之中。URI 是 uniform resource identifier(統一資源標識符)
的縮寫,它定義了接受內容的協議以及附帶的相關內容,若是附帶的相關內容是一個地址,那麼此時的 URI 也是一個 URL (uniform resource locator
)(統一資源定位符),如:chrome
ftp://10.1.1.10/path/to/filename.ext
http://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 類型來解析數據。xss
第三部分是編碼設置,默認編碼是 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:
可是部分瀏覽器對 data URI 的使用存在限制:
長度限制,長度超長,在一些應用下會致使內存溢出,程序崩潰
Opera 下限制爲 4100 個字符,目前已經去掉了這個限制
IE 8+ 下限制爲 32,768 個字符(32kb),IE9 以後移除了這個限制
在 IE 下,data URI 只容許被用到以下地方:
在 IE 下,Data URI 的內容必須是通過編碼轉換的,如 「#」、」%」、非 US-ASCII 字符、多字節字符等,必須通過編碼轉換☞ 低版本IE的解決之道 - MHTML
MHTML 就是 MIME HTML,是 「Multipurpose Internet Mail Extensions HyperText Markup Language」 的簡稱,它就像一個帶着附件的郵件通常,以下所示:
/** FilePath: http://example.com/test.css */
/*!@ignore
Content-Type: multipart/related; boundary="_ANY_SEPARATOR"
--_ANY_SEPARATOR
Content-Location:myidBackground
Content-Transfer-Encoding:base64
iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//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);
}
上方的一串註釋就像是一個附件,這個附件內容是一個名叫 的 編碼圖片,在一個 class 叫作 的 css 中用到了它。這裏有幾點須要注意:myidBackgroundbase64myid
_ANY_SEPARATOR
能夠是任意內容_ANY_SEPARATOR
,不然在 Vista 和 Win7 的 IE7 中會出錯。這裏存在一個坑:部分系統兼容模式下的 IE8 也認識 css 中的 hack 符號 *
,可是不支持 mhtml
,因此上面的內容不會生效。處理方案估計就只有使用 IE 的條件註釋了。
HTTPS 打開頁面,當在 IE六、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><!--
這裏能夠很大程度的發散,頗有意思,值得讀者去深究。