文本转数据URI转换器

按 RFC 2397 的语法把一段文本就地拼成 data URI:data:[<mediatype>][;base64],<data>。媒体类型可选,base64 标记可选,逗号之后是数据本体。本页同时给出 base64 与百分号编码两种写法的长度比对,让你按内容挑更短的那种,全程在本浏览器完成,文本不会上传到任何服务器。

默认示例 20 字节:base64 得 28 字符(1.4 倍),百分号编码得 48 字符(2.4 倍)。中文占多数时 base64 更短。
data:text/plain;charset=utf-8;base64,SGVsbG8sIOafs+azieW3peWFtyE=
原始字节20
编码后字符28
膨胀倍数1.40000
前缀长度37
URI 总长度65

长度阶梯表从 1 字节列到 16 MB,逐行给出 base64 字符数、膨胀倍数与两种口径的百分号字符数;默认显示 12 行。

使用方法

  1. 「待转换文本」默认写着一句 Hello, 柳泉工具!,改成你自己的内容即可;改完按 Ctrl+Enter(Mac 上是 Cmd+Enter)重新生成,框被清空时点「生成 data URI」会把示例填回去。
  2. 「媒体类型」下拉给出四种常见写法:text/plain;charset=utf-8、text/html、image/svg+xml、application/json,也可选「自定义」自己填。
  3. 「编码方式」二选一。base64 把任意字节压进 A-Za-z0-9 加号斜杠这 64 个字符再加等号补位,任何内容都能安全通过;百分号编码保留原文的可读性,代价是每个非 ASCII 字节变成三个字符。
  4. 「长度上限(字符)」默认 100000,最小 100、最大 100000、步长 100。文本超过它不会硬截断,而是给出写明当前长度的提示——data URI 太长本来就会被截断。
  5. 结果区先给一行结论,下面是完整的 data URI,再下面是五格统计:原始字节数、编码后字符数、膨胀倍数、前缀长度、URI 总长度。
  6. 统计下面是一张 24 行长度阶梯表,从 1 字节列到 16 MB,逐行给出 base64 字符数与两种口径的百分号字符数;默认显示 12 行,点「加载更多」展开全部,点「导出 CSV」存成带 BOM 的文件。
  7. 「复制 URI」把整串 data URI 放进剪贴板;「复制对照表」复制正文里的字符编码对照表,制表符分隔可直接粘进表格软件。
  8. 文本区为空时点生成会自动填回示例;自定义类型为空、不含斜杠、含逗号或空格、文本超长,都会给出写明原因的提示,不会拿上一次的结果冒充本次输出。

这个文本转数据URI转换器能解决什么问题

把一段文本变成可以直接嵌进文档的字符串,是前端模板、邮件模板与单文件交付里反复出现的小需求。RFC 2397 给 data 这个方案下的定义是 data:[<mediatype>][;base64],<data>,两段方括号都可省略,省略媒体类型时按 text/plain;charset=US-ASCII 处理。这一页做的就是按这条语法把文本就地拼成 URI。

第一类是内联小资源。一个几十字节的 SVG 图标、一段 JSON 配置,单独发一次请求的握手成本远高于内容本身,写成 data URI 直接塞进 url() 就能省掉这次往返。SVG 与 HTML 这类文本格式还有额外好处:可以不用 base64,直接百分号编码,人还能读懂里面的标签。

第二类是单文件交付。把一个页面连同它依赖的说明文本、配置与图标打成一个文件,发给别人双击就能打开,不需要附带目录。这类场景对体积敏感,本页把两种编码的长度并排列出来,就是为按内容挑更短的那种。

第三类是邮件与富文本模板。部分邮件客户端不接受外链图片与外链样式,把小图标转成 data URI 是绕开限制的常用做法。但要注意 data:text/html;base64, 能承载可执行脚本,属于 XSS 载体,用在别人能控制内容的场合风险极高。

第四类是判断到底该用哪种编码。纯 ASCII 时百分号编码是 1 倍、base64 是 1.33333333333 倍,百分号更短;内容是中文时百分号变成 3 倍、base64 仍是 1.33333333333 倍,base64 反而更短。同一决策在两种内容下结论相反,靠猜很容易选错。

计算原理与变量说明

data URI 只有三段。第一段是 scheme 与可选的媒体类型,形如 data:text/plain;charset=utf-8;第二段是可选的 ;base64 标记,只在写了媒体类型之后才出现,写成 mediatype;base64,若媒体类型整段省略则要写成 data:;base64,...;第三段是逗号之后的数据本体。

base64 的换算很机械:每 3 个字节编成 4 个字符,体积上限是 1.33333333333 倍,也就是多出 33.33 个百分点。除不尽的余数靠等号补位——余 1 字节补两个等号、余 2 字节补一个、整除补零个。补位让小数据上的倍率明显高于 1.333:1 字节编成 4 字符是 4 倍,10 字节编成 16 字符是 1.6 倍,1 KB(1024 字节)编成 1368 字符是 1.33594 倍,1 MB 编成 1398104 字符,已非常接近极限值。

百分号编码的换算方向相反,它按字节工作:一个字节变成一个百分号加两位十六进制,占 3 个字符。纯 ASCII 时每个字符恰好一个字节,长度不变,是 1 倍;UTF-8 下一个汉字占 3 个字节,百分号编码后是「百分号 XX」重复三次共 9 个字符,膨胀到 3 倍。「中文」这两个字原始 6 字节,百分号编码后是 18 个字符,正是 3 倍。

于是两种编码的优劣完全由内容决定:ASCII 占多数时百分号更短,非 ASCII 占多数时 base64 更短。分界线并不神秘——百分号对每个非 ASCII 字节收 3 个字符,base64 对每个字节一律收 1.33333333333 个字符,非 ASCII 比例越过某个点,base64 就会反超。

媒体类型推荐编码说明
text/plain;charset=utf-8百分号编码纯文本多数字符不需要转义,可读性最好
text/html百分号编码标签结构可保留;含大量特殊字符时改 base64
image/svg+xml百分号编码尖括号与引号必须转义,其余可读
application/json百分号编码引号与花括号转义后仍能辨认字段
image/png必须 base64二进制流,百分号编码会膨胀到 3 倍
font/woff2必须 base64二进制流,且体积大,超过几十 KB 建议改用 blob

安全边界要单独说。data:text/html;base64, 里可以放完整的 HTML 与脚本,因此它是 XSS 的常见载体,内容安全策略的 default-src 指令会拦下来自 data: 的脚本。另一方面,Chrome 60 与 Firefox 59 之后浏览器禁止顶级导航到 data: URL:在地址栏粘贴或用脚本打开 data: 地址会被拒绝,只有 img、iframe、CSS url() 这类子资源加载仍然可用。

最后是它与 blob: URL 的分工。data: 是内联字符串,同步可用、不需要显式释放,但复制一份就多占一份内存;blob: 是对内存中对象的引用,用完必须调用 revokeObjectURL 释放,否则那块内存不会被回收。体积超过几十 KB 时 blob: 通常更合适。

完整示例(数值仅作演示)

打开页面时的默认值是文本 Hello, 柳泉工具!、媒体类型 text/plain;charset=utf-8、编码 base64、长度上限 100000。这句文本共 12 个字符、20 个字节(8 个 ASCII 字符加 4 个汉字,每个汉字 3 字节);base64 编码后是 28 个字符 SGVsbG8sIOafs+azieW3peWFtyE=,末尾一个等号补位,因为 20 除以 3 余 2。完整 URI 前缀 37 个字符,总长 65 个字符。

把编码方式切到百分号编码,同一句变成 48 个字符 Hello%2C%20%E6%9F%B3%E6%B3%89%E5%B7%A5%E5%85%B7!:逗号变 %2C、空格变 %20、四个汉字各占 9 个字符。48 比 28 长了 20 个字符,膨胀 2.4 倍,中文占多数时 base64 的优势一目了然。

换成纯 ASCII 的 Hello, world!,结论立刻反过来:13 个字节,base64 编成 20 字符,百分号编码只有 17 字符(Hello%2C%20world!)。同一套规则,内容一换,更短的那一边就换了人。

文本与 data URI 对照表

下表列出常见字符在百分号编码下的写法。base64 的优势正在于这些字符全都不出现在它的字符集里,不需要处理任何保留字符。

字符百分号编码是否需要转义
空格%20必须,空格会截断 URI
逗号 ,%2C必须,逗号是前缀与数据的分界
冒号 :%3A视位置而定,媒体类型里的冒号保留
斜杠 /%2F必须,避免被当成路径
分号 ;%3B建议转义,分号是参数分隔符
加号 +%2B建议转义,form 口径下会被解成空格
百分号 %%25必须,否则被当成转义起始
井号 #%23必须,井号之后是片段标识
双引号 "%22必须,塞进 HTML 属性时会打断属性
小于号 <%3C必须,否则被当成标签起始
汉字「柳」%E6%9F%B3必须,一个汉字 3 字节共 9 个字符
等号 =%3D建议转义,易与查询串混淆

第二张表给出 base64 的长度阶梯,按每 3 字节编成 4 字符的规则算出,用来估算稍大的资源会不会超预算。

原始字节base64 字符膨胀(倍)
144.00000
10161.60000
64881.37500
1281721.34375
2563441.34375
5126841.33594
102413681.33594
204827321.33398
409654641.33398
8192109241.33350
16384218481.33350
32768436921.33337

结果边界、舍入与适用说明

常见问题

data URI 里的媒体类型能省略吗?

能。RFC 2397 里媒体类型与 base64 标记都在方括号中,都是可选的。省略时按 text/plain;charset=US-ASCII 处理,非 ASCII 字符会失去编码声明,写中文请带上 charset=utf-8。

;base64 标记一定要跟在媒体类型后面吗?

是的。语法是 mediatype;base64,分号是媒体类型的参数分隔符。若媒体类型整段省略又要用 base64,得写成 data:;base64,...,分号直接跟在冒号后面。

base64 为什么总是多出三分之一的体积?

它把 3 个字节(24 位)重新切成 4 个 6 位组,每个 6 位组用一个可打印字符表示,字节数与字符数之比恒为 3 比 4,即膨胀 1.33333333333 倍。小数据上还会多出等号补位,倍数更高一些。

中文内容到底该用 base64 还是百分号编码?

用 base64。UTF-8 下一个汉字 3 字节,百分号编码后是 9 个字符,膨胀 3 倍;base64 对任何字节都只收 1.33333333333 倍。反过来,纯 ASCII 内容用百分号编码是 1 倍,比 base64 短,而且人还能读懂。

为什么在新标签里打不开生成的 data URI?

Chrome 60 与 Firefox 59 之后,浏览器禁止顶级导航到 data: URL,这是针对钓鱼与混淆攻击的统一限制。img 的 src、iframe 的 src、CSS 的 url() 这些子资源加载不受影响。

把 HTML 转成 data URI 安全吗?

内容本身可控就没问题,但 data:text/html;base64, 能承载脚本,属于典型的 XSS 载体。若内容里掺入用户输入,务必先转义;站点层面可以用内容安全策略的 default-src 指令拦下来自 data: 的脚本。

多大的内容适合做成 data URI?

经验值在几十 KB 以内。IE8 时代硬上限是 32 KB(32768 字符),现代浏览器没有这个限制,但服务器、邮件网关与剪贴板各有自己的上限。超过这个量级请改用 blob: URL 或外链文件。

输入的内容会上传到服务器吗?

不会。文本、媒体类型与编码选项只在本页脚本里参与运算,页面没有发起任何网络请求,刷新后输入即回到默认示例。

相关工具