关于Data URI

【新增】: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:

  • Firefox 2+
  • Opera 7.2+
  • Chrome (全部版本)
  • Safari (全部版本)
  • Internet Explorer 8+

可是部分浏览器对 data URI 的使用存在限制:

  • 长度限制,长度超长,在一些应用下会致使内存溢出,程序崩溃

    Opera 下限制为 4100 个字符,目前已经去掉了这个限制
    IE 8+ 下限制为 32,768 个字符(32kb),IE9 以后移除了这个限制
  • 在 IE 下,data URI 只容许被用到以下地方:

    在 IE 下,Data URI 的内容必须是通过编码转换的,如 “#”、”%”、非 US-ASCII 字符、多字节字符等,必须通过编码转换
    • object (images only)
    • img、input type=image、link
    • CSS 中容许使用 URL 声明的地方,如 background

☞ 低版本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 下的安全提示

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><!--

这里能够很大程度的发散,颇有意思,值得读者去深究。

☞ 扩展阅读

相关文章
相关标签/搜索