Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

如何理解data URL? #212

Open
FrankKai opened this issue Apr 23, 2020 · 5 comments
Open

如何理解data URL? #212

FrankKai opened this issue Apr 23, 2020 · 5 comments

Comments

@FrankKai
Copy link
Owner

dataURL

canvas有一个非常常用的方法canvas.toDataURL(),它会将canvas转化为data URL的格式。
通常情况下这个data URL的类型为image。
看看下面的例子:

<canvas id="canvas" height="2" width="2"></canvas>

var canvas = document.getElementById('canvas');
var dataURL = canvas.toDataURL();
console.log(dataURL);
/*
* data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAADklEQVQYV2NkgAJGGAMAAC0AA03DhRMAAAAASUVORK5CYII=
*/

那么这个以data:[MIME type];base64,开头的data URL到底是什么东西呢?

  • 初识data URL
    • data URL与传统的url有什么区别?
    • data URL在浏览器地址栏输入后是怎样的?
  • data URL语法
    • data URL由哪四部分组成?
    • [<mediatype>]详情
    • [;base64]<data>详情
    • 常见的data URL形式
  • 字符串base64编解码的多种语言实现
    • 为什么要用base64来表示data URL中的?
    • unix,javascript,node,python,php,java,.net实现base64编码
  • data URL常见问题
@FrankKai
Copy link
Owner Author

初识data URL

  • data URL是一种特殊格式的url,它的前缀是data:
  • data URL允许内容的创建者将小文件嵌入在documents中
  • 过去被叫做data URIs,直到WHATWG将其更名为data URL(s)

data URL与传统的url有什么区别?

现代浏览器将data url视作唯一的不透明来源,而不是负责导航的url。
如何理解这句话呢?看一下这个例子:

// data URL
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAADklEQVQYV2NkgAJGGAMAAC0AA03DhRMAAAAASUVORK5CYII=
// 传统的URL
https://www.google.com

由上面的结果可以看出:
data URL与传统的url不同。
传统的url在浏览器地址栏中输入,可以直接导航到目标地址;而data URL则是一个data的url表现,可以理解为用url代表数据。
通常情况下,这里的数据指代的是图片。

data URL在浏览器地址栏输入后是怎样的?

通常情况下,可以看到这个url代表的图片。

<!DOCTYPE html>
<html lang="en">
  <body>
    <canvas id="canvas"></canvas>
  </body>
  <script>
    var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");
    ctx.font = "48px serif";
    ctx.fillText("Hello Canvassssssssss", 0, 75 + 24);
    var dataURL = canvas.toDataURL();
    console.log(dataURL);
  </script>
</html>

image

@FrankKai
Copy link
Owner Author

data URL语法

data URL由哪四部分组成?

data:[<mediatype>][;base64],<data>
组成 含义
data: 前缀
[<mediatype>] MIME type 代表数据的类型
[;base64] 可选的base64标识
<data> 数据本身

[<mediatype>]详情

  • mediatype是一个MIME type的字符串,比如'image/jpeg'。
  • 如果忽略的话,默认是"text/plain;charset=US-ASCII"。
  • canvas.toDataURL()并没有忽略,默认MIMIE type为"image/png"。

[;base64]<data>详情

  • 如果data是纯文本,你可以简单的嵌入文本(根据document类型使用适当的实体或者转义)。
  • 如果data不是纯文本的话,可以标识为base64,并且嵌入base64编码的二进制数据。

常见的data URL形式

  • 简单的text/plain数据
  • 简单的text/palin数据的base64形式
  • HTML片段:普通标签
  • HTML片段:执行js的script标签
简单的text/plain数据

Hello World!

data:,Hello%2C%20World! // MIME type和;base64都没有,data和数据间只有`:,`

注意引号和空格的percent-encoding(URL-encoding)。
对于CSV数据(”text/csv“),percent-encoding需要保留分隔电子表格行的行尾。

简单的text/palin数据的base64形式

Hello World!

data:text/plain;base64,SGVsbG8sIFdvcmxkIQ==
HTML片段:普通标签

<h1>Hello, World!</h1>

data:text/html,%3Ch1%3EHello%2C%20World!%3C%2Fh1%3E
HTML片段:执行js的script标签

<script>alert('hi');</script>

data:text/html,<script>alert('hi');</script>

执行js的script标签,注意闭script标签是需要的。

@FrankKai
Copy link
Owner Author

字符串base64编解码的多种语言实现

为什么要用base64来表示data URL中的<data>

  • base64字符串是用64进制来表示二进制数据的,它是一个ASCII字符串。
  • 由于仅仅是通过ASCII字符组成的,所以base64字符串是url-safe的,因此才将base64应用于data URL的<data>中。

unix,javascript,node,python,php,java,.net实现base64编码

"foo@gmail.com"
"Zm9vQGdtYWlsLmNvbQ=="
1.unix (author: Peng Zhao)

解码:echo "Zm9vQGdtYWlsLmNvbQ==" | base64 -D
编码:echo "foo@gmail.com" | base64

2.javascript (author: Kai Gao)
var encodedData = window.btoa("foo@gmail.com"); // 编码
var decodedData = window.atob("Zm9vQGdtYWlsLmNvbQ=="); // 解码
console.log(encodedData,decodedData)
3.nodejs (author: Kai Gao)
//base64编码
var  b = new Buffer("foo@gmail.com");
var s = b.toString('base64')
console.log("邮箱编码:"+s)
//base64解码
var b = new Buffer("Zm9vQGdtYWlsLmNvbQ==","base64")
var s = b.toString();
console.log("邮箱解码:"+s)
4.python (author: Peng Zhao)
import base64
base64.b64encode("foo@gmail.com")
base64.b64decode("Zm9vQGdtYWlsLmNvbQ==")
5.php (author: Chuang Shen)
<?php
$a = 'foo@gmail.com';
	$b = base64_encode($a);//编码
	echo $b;
	$c = base64_decode($b);//解码
	echo $c;  
?>
6.java (author: Chuang Shen)
String str = "foo@gmail.com";
    	String encodeStr = new String(Base64.encode(str.getBytes()));
    	System.out.println(encodeStr);
    	String decodeStr = Base64.base64Decode(encodeStr);
    	System.out.println(decodeStr);
7..net (author: Peng Li)
static void Main(string[] args)
        {
            Console.WriteLine("输入:");
            var str = Console.ReadLine();
            //加密
            byte[] EncryptionByte = Encoding.UTF8.GetBytes(str);
            var EncryptionStr = Convert.ToBase64String(EncryptionByte);

            Console.WriteLine("加密结果:" + EncryptionStr);

            //解密
            byte[] DecryptionByte = Convert.FromBase64String(EncryptionStr);
            var DecryptionStr = Encoding.UTF8.GetString(DecryptionByte);

            Console.WriteLine("解密结果:" + DecryptionStr);

        }

查看字符串base64编解码的多种语言实现弄清base64多语言实现的来龙去脉。

@FrankKai
Copy link
Owner Author

data URL常见问题

罗列一些在创建和使用data URL时的常见问题。

data:text/html,lots of text...<p><a name%3D"bottom">bottom</a>?arg=val

其实它代表的是:

lots of text...<p><a name="bottom">bottom</a>?arg=val
  • 语法
  • HTML中的格式
  • 长度限制
  • 异常处理的缺失
  • 不支持字符串查询
  • 安全问题

语法

data URL的格式非常简单,很容易忘记在data前面添加一个逗号,或者是错误的将数据编码为base64格式。

HTML中的格式

data URL在文件中提供了一个文件,这个文件相对于闭文档的宽度可能非常宽。
作为一URL,data应该将空白格式化好(换行、tab、或者空格),但是在使用base64编码时会有一些问题。

长度限制

尽管firefox支持无现场的data URL长度,但是浏览器不需要支持任何最大特定长度的数据。例如Opera 11浏览器将URL的长度限制到65535,data URL限制到65529(65529指的是base64 encoded后的<data>长度)。

主流浏览器data URL长度限制
  • Chrome - 2MB for the current document. Otherwise the limit is the in-memory storage limit for - arbitrary blobs: if x64 and NOT ChromeOS or Android, then 2GB; otherwise, total_physical_memory / 5 (source).
  • Firefox - unlimited
  • IE ≥ 9 & Edge - 4GB

引自:Data protocol URL size limitations

异常处理的缺失

media的无效参数,或者‘base64’排版错误,都会被忽略,但是不会报错出来

不支持字符串查询

data URL的数据部分是不透明的,所以如果使用query string(比如<url>?parameter-data)去查询时,将只在数据中包含URL的查询字符串。也就是说查询无效,query也会被当做数据的一部分。

安全问题

许多安全问题(如网络钓鱼)都与data url相关,并在浏览器的顶层导航到它们。
为了解决这些问题,在Firefox 59+中(发布版本,从58开始),对数据的顶层导航data:// urls已经被禁止。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant