需要使用 Base64 格式吗?那么本网站正好适合您!使用我们的在线工具对数据进行编码或解码,便捷好用。

Ruby 中的 Base64 编码:完整指南

你的数据有一个不接受它当前样子的目的地。一张必须住进 JSON 文档里的图片。一枚必须穿过 URL 的令牌。一个必须活过七位文本协议设计的附件。一个必须坐在环境变量里又不能破坏引号引用的秘密。在每一个这样的地方,这里和那里之间的某个东西正要毁掉你的二进制 - 而解法有个名字:Base64。

在 Ruby 里,整个工作住在随语言发货的一个模块里。三个编码器,什么都不用装,输出在你运行代码之前就能精确预测到每一个字符。这种可预测性是大多数指南跳过的故事的一半,因为编码正是惊喜收费的地方:一个末尾换行悄悄爬进你的 JSON,一个你没要的换行劈开你的令牌,一次选错的字母表毁掉一个 URL。这份指南走一遍全部三个编码器、输出的数学,以及 Ruby 开发者真正会编码的每一种载荷,让惊喜不再成为惊喜。

开始之前快速复习一下:Base64 每三个字节重写一次数据,从 64 符号字母表中发出四个字符,当输入不能被三整除时加上一两个 = 字符作为填充 - 这也是输出最终比输入大约三分之一大的原因。本站首页已经把格式讲得很透彻,所以这篇文章把格式部分压缩成一口气,直接开始干活。

你需要哪个编码器?

Ruby 给你三个编码器,而它们之间的选择是一道三问小测验:输出可以包含换行吗?可以包含 +/ 吗?可以包含填充吗?这是全部阵容:

编码器 输出形状 换行 填充 何时伸手拿它
Base64.strict_encode64(bin) 一行,标准字母表 从不 永远存在 JSON、令牌、API、文件 - 安全的默认选择
Base64.encode64(bin) 多行,标准字母表 每 60 个字符之后,外加末尾一个 永远存在 邮件正文和其他按行组织的文本协议
Base64.urlsafe_encode64(bin, padding: true) 一行,连字符-下划线字母表 从不 你说了算,默认开启 任何会落在 URL、cookie 或标识符里的东西

如果你在时间压力下做决定,简短答案是:默认 strict_encode64,结果要在 URL 里旅行时用 urlsafe_encode64,只有接收方是想让短行的文本协议时才用 encode64。下面所有内容解释为什么,以及每个选择在哪里悄悄让你付出代价。

strict_encode64:主力干将

Base64.strict_encode64 是你真正会在绝大多数代码里使用的编码器。它产出恰好一行的输出,永远带着正确的填充,来自标准字母表:

require "base64"
Base64.strict_encode64("hello world")
# => "aGVsbG8gd29ybGQ="
Base64.strict_encode64("s")
# => "cw=="

而且因为算法是确定性的,你可以从输入预测输出的精确长度 - 不用猜,数据库列里也不会有差一错误。下面这张表就是全部算术:

输入长度 输出长度 末尾填充
3n 字节(整除) 4n 个字符
3n + 1 字节 4n + 4 个字符 两个 =
3n + 2 字节 4n + 4 个字符 一个 =

所以 11 个字节变成 16 个字符,100 个字节变成 136,一个 1 MB 的文件变成大约 1.33 MB 的文本。那三分之一的增长是你发货的每个 Base64 载荷的入场费,也是每当某个列、缓存或 API 速率限制开始发紧时,该揣在后兜里的数字。

Base64.strict_encode64("123")
# => "MTIz"        3 字节进,4 个字符出
Base64.strict_encode64("1234")
# => "MTIzNA=="   4 字节进,8 个字符出,2 个填充字符
Base64.strict_encode64("12345")
# => "MTIzNDU="   5 字节进,8 个字符出,1 个填充字符

encode64:那个会加换行的

Base64.encode64 是经典款,它有一个行为结束过不止一个下午:它给输出折行。每 60 个字符,它开始新的一行,而且永远以一个末尾换行收尾:

Base64.encode64("hello world")
# => "aGVsbG8gd29ybGQ=\n"
Base64.encode64("*" * 46)
# => "KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq\nKg==\n"

折行不是 bug - 它是从这个方法在 MIME 世界的老家继承来的特性,在那里,长行是协议违规。Ruby 的 mail gem 刻意依赖它 - 它的 Base64 编码器甚至带着这样一条注释:Ruby 的折行让输出保持在 SMTP 行长度限制之内。如果你在编码邮件正文,encode64 是在帮你。

但在其他所有上下文里,折行是一笔税。最常见的事故,是一个 JSON 文档里的 Base64 值突然跨了两行:

payload = { "logo" => Base64.encode64(File.binread("logo.png")) }
puts payload.to_json
# logo 的值带着没人要的换行

同一个 bug 的小双胞胎是短字符串上的末尾换行:Base64.encode64("s") 返回 "cw==\n",所以你粘贴进 URL 或拿去和期望值比较的令牌,会因一些让你追二十分钟的原因而失败。解药是 strip - 但更好的解药是 strict_encode64,它从不添加一个你没挣到的字符。还有一个值得知道的讨喜不对称:空输入产生一个不带末尾换行的空字符串,所以 Base64.encode64("") 就是 ""

urlsafe_encode64:链接安全字母表

标准字母表里有两个字符,在任何有 URL 解析器盯着的地方都会惹麻烦:+(在查询字符串里是空格)和 /(路径分隔符)。RFC 4648 用一个交换解决了这个问题 - - 取代 +_ 取代 / - Ruby 在 Base64.urlsafe_encode64 里实现了它:

Base64.urlsafe_encode64("\xfb\xef\xbe".b)
# => "----"
Base64.urlsafe_encode64("\xff\xff\xff".b)
# => "____"

这两个例子就是字母表的展示:同样的字节,标准编码器渲染成 ++++////,在这里输出为 ----____ - 这些字符在 URL、路径、文件名和表单字段里都能幸存,完全不需要百分号编码。输出一行,就像 strict_encode64 一样。

该方法唯一的选项是 padding: 关键字,在 Ruby 2.3 加入,也是那个必须知道的选项。JSON Web Token 规范要求 base64url 不带填充,许多其他令牌方案也是如此:

Base64.urlsafe_encode64("*")
# => "Kg=="
Base64.urlsafe_encode64("*", padding: false)
# => "Kg"

关掉填充后,长度算术就变了:3n + 1 字节现在产生 4n + 2 个字符,3n + 2 字节产生 4n + 3。解码侧能应付 - Ruby 的 urlsafe_decode64 会自己补上缺失的填充 - 所以不带填充的输出可以安全发出,但当对方是严格的 RFC 2045 读取器时,带填充的输出是更友好的默认。一个提醒:只有当规范明确要求时才关掉填充。它省下一两个字符,却买回一整类解码器抱怨。

Ruby 实际编码的是什么:字符串是字节

在讲用例之前,先说一个塑造一切的 Ruby 特有事实:一个 Ruby 字符串是一个戴着编码标签的字节序列,而编码器只看字节。标签告诉 Ruby 如何显示和比较这个字符串;它不改变被编码的内容:

require "base64"
s = "h\u{e9}llo"
puts s.encoding
# => UTF-8
puts s.bytes.length
# => 6   带重音的 e 是 2 个字节
Base64.strict_encode64(s)
# => "aMOpbGxv"

这就是“为什么我的输出比我预期的长”背后的陷阱:你敲进去的字符串通常按字符算比按字节算更短,而 Base64 按字节收费。反方向同样安静 - 一个无效的 UTF-8 字符串会被毫无抱怨地编码,因为编码器没有任何东西可验证:

broken = "h\u{e9}llo".b.force_encoding("UTF-8")
broken.setbyte(1, 0xFF)
puts broken.valid_encoding?
# => false
Base64.strict_encode64(broken)
# => 某段 base64,没有错误,字节就是字节

对于真正的二进制,完全跳过文本那套机器,用 pack 构造字节,或者用 File.binread 读取它们。一个让人满足的例子是 PNG 签名 - 地球上每个 PNG 文件开头的那 8 个字节:

png_magic = [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A].pack("C*")
Base64.strict_encode64(png_magic)
# => "iVBORw0KGgo="

JWT:签名一份同样可读的数据

JSON Web Token 是 Ruby URL 安全编码器最高调的消费者。一个令牌是三段 base64url 段用点号连接 - 头部、载荷、签名 - 而规范说得很明确:字母表必须是 URL 安全的那个,填充必须关掉。jwt gem 处理这一切:

# Gemfile: gem "jwt"
require "jwt"
token = JWT.encode(
  { sub: "1234567890", name: "Alice", exp: Time.now.to_i + 3600 },
  "my-secret-key",
  "HS256"
)
puts token
# => eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkFsaWNlIi...
payload, header = JWT.decode(token, "my-secret-key", true, algorithm: "HS256")
puts header
# => {"alg"=>"HS256"}

你也可以看着 Base64 层在令牌里干活,因为这些段就是 JSON 的 base64url:

require "base64"
require "json"
payload_json = JSON.generate({ "sub" => "1234567890", "name" => "Alice" })
segment = Base64.urlsafe_encode64(payload_json, padding: false)
puts segment
# => eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkFsaWNlIn0

这个用例配两条规则。永远不要在生产环境手工搓 JWT - 签名才是让令牌不只是自供状的东西 - 而且用 gem 解码时,像上面那样在选项哈希里把算法钉死,让令牌自己的头部不能替你选验证方法。

HTTP Basic 认证:构建头

HTTP 里说“我是谁”的最老方式,至今也最简单:把凭据 Base64 编码,放在 Basic 这个词后面,发送这个头。在 Ruby 里构建它只要一行:

require "base64"
credentials = Base64.strict_encode64("alice:s3cr3t!")
puts "Basic #{credentials}"
# => Basic YWxpY2U6czNjcjN0IQ==

Ruby 的标准库在 Net::HTTP 里替你做了完全一样的事,直接调用核心 pack 模板 - ["user:pass"].pack("m0") 就是 basic_auth 底层的最终形态:

require "net/http"
request = Net::HTTP::Get.new("https://example.org/api")
request.basic_auth("alice", "s3cr3t!")
puts request["Authorization"]
# => Basic YWxpY2U6czNjcjN0IQ==

还有一个安全警告,说一次以便留档:Base64 是翻译器,不是锁。Basic 认证头里的凭据,任何能读这个包的人都能读。这个头只在 HTTPS 之上才可接受,在那里,传输层做真正的保护。

Data URI:内联图片与字体

data URI 是 web 对“我想要这张图,但不要单独的文件”的回答:一个媒体类型、单词 base64、一个逗号,然后是字节。单文件 HTML 演示靠它携带 logo,favicon 靠它藏进 CSS,生成的图片靠它完全住在一个模板字符串里:

require "base64"
png = File.binread("logo.png")
data_uri = "data:image/png;base64,#{Base64.strict_encode64(png)}"
css = "background-image: url(#{data_uri});"
puts css.length
# => 你的样式表,减去一次 HTTP 请求

这里用 strict_encode64 - 载荷是一行干净的数据,不折行,无换行。还要盯住尺寸:你内联的图片会膨胀大约三分之一,所以 data URI 在小资源(favicon、logo、图标字体)上发光,在大资源上臃肿。一张 2 MB 的英雄大图变成你 HTML 文档里的 2.7 MB,你的用户会在第一次 4G 滚动时感受到它。

邮件:Base64 的来处

这篇文章里其他所有用例都是它的后裔。SMTP 在 20 世纪 80 年代为七位文本的短行设计,换句话说,它带不动 JPEG。解法 - 先是 Privacy-Enhanced Mail,然后是 1993 年的 MIME - 是用 64 符号字母表把二进制重写成文本,那正是你今天在用的格式。伤疤在 Ruby 的输出里仍看得见:encode64 在 60 个字符处折行 - 这个宽度并不服务于某个特定协议,你稍后会看到,但足够短,能让邮件保持礼貌。

实践中你会让 mail gem 做 MIME 工作。挂上一个二进制文件,gem 会选 Base64 编码器、折好行、写好头:

# Gemfile: gem "mail"
require "mail"
message = Mail.new do |m|
  m.from = "dev@example.org"
  m.to = "ops@example.org"
  m.subject = "Binary report"
  m.add_file("report.bin")
end
puts message.encoded
# 附件部分带着 Content-Transfer-Encoding: base64 头

头里的非 ASCII 文本得到同样待遇,只是换了一套略不同的行头:RFC 2047 编码词,把 Base64 包在问号之间的字符集标签里,像 =?UTF-8?B?w7wgc2VjcmV0cw==?=。如果你哪天手工构建或解析它们,里面的 Base64 是普通的那种,用 decode64 解码,再贴上这个词声明的字符集标签。

密钥与证书的 PEM 护甲

密钥和证书穿着 PEM 护甲,而护甲就是带框的 Base64:一行 BEGIN、每行 64 个字符的编码字节,加上一行 END。如果你需要从原始 DER 字节生成一个 PEM 文件,构造是一个两步包裹:

require "base64"
der_bytes = File.binread("server.der")
body_lines = Base64.strict_encode64(der_bytes).scan(/.{1,64}/)
pem = (["-----BEGIN PRIVATE KEY-----"] + body_lines +
  ["-----END PRIVATE KEY-----"]).join("\n") + "\n"
File.write("server.key", pem)

两条备注。第一,你几乎永远用不到这个,因为 openssl gem 替你写 PEM(key.to_pem),而且 BEGIN 和 END 行之间的标签必须与里面的东西匹配 - 搞错了会产出一个互联网上每个工具都拒绝的文件。第二,这里的行长是 64,PEM 的经典宽度;Ruby 的 encode64 折在 60,而每个像样的 PEM 解析器都完全无视行长,所以两种宽度都能正常解码。

文件:.b64 约定

Base64 世界里最常见的文件格式,就是一个带 .b64(或 .base64)扩展名的纯文本文件,里面装着一个编码后的载荷 - 把它想成“那个文件,但贴到哪里都安全”。从 Ruby 生成它是一行流:

require "base64"
File.write("payload.b64", Base64.strict_encode64(File.binread("payload.bin")))
puts File.size("payload.b64")
# => 大约是原始大小的 1.33 倍

strict_encode64,让文件只装一行干净的数据 - 这是大多数解码工具(以及 Ruby 的严格解码器)期望的约定。读回来是镜像操作:读、解码,然后用二进制模式写出字节,让没有任何东西在出门路上被篡改:

encoded = File.read("payload.b64")
bytes = Base64.strict_decode64(encoded)
File.binwrite("restored.bin", bytes)

如果你的 .b64 文件来自会折行的工具 - 某些 base64 CLI 变体确实如此 - 在严格解码前剥掉换行,或者用宽容的解码器,它会免费跳过换行。

配置文件、环境变量与数据库

每当二进制数据必须住进一份文本文档,Base64 就是那座桥。这个模式在三处重复出现,各带一点小变化。

环境变量和 .env 文件装不下原始字节,所以字节在离开拥有它们的那台机器之前就被编码:

require "base64"
# 在某处配置应用的地方
ENV["APP_LOGO"] = Base64.strict_encode64(File.binread("logo.png"))
# 在某处应用启动的地方
b64 = ENV.fetch("APP_LOGO")
File.binwrite("logo.png", Base64.decode64(b64))

YAML 有原生的二进制类型,Psych 替你处理 Base64 - 一个 BINARY 字符串 dump 到 YAML 会输出为 !binary 标量,加载回来字节级一致:

require "yaml"
yaml_text = YAML.dump({ "logo" => File.binread("logo.png") })
puts yaml_text.lines.first(2)
# => "---"
# => "logo: !binary |-"
data = YAML.load(yaml_text)
puts data["logo"].encoding
# => ASCII-8BIT

在数据库里,问题是存储类型,不是编码。如果你的数据库有真正的二进制列 - BLOB、BYTEA、VARBINARY - 就用它,让驱动去携带字节。把 Base64 塞进 TEXT 列,是当存储层只说字符串时的模式:某些文档型数据库、JSON 形状的 API,或者一个你改不动的遗留 schema。代价是列上三分之一的尺寸税,外加一份纪律:在每个边界上,进的时候编码,出的时候解码,绝无例外。

以文本旅行的校验和

哈希是二进制的,但校验和大多以文本旅行:文件完整性清单、缓存键、指纹、日志行。Ruby 的每个摘要类都有一个 base64digest 方法,一次调用完成编码:

require "digest"
Digest::SHA256.base64digest("hello")
# => "LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ="

输出是带填充的标准 Base64 - 与 Base64.strict_encode64(Digest::SHA256.digest("hello")) 的产物相同 - 所以存、比较、粘贴都安全。唯一的决定是保持一致:用 Base64 生成的校验和清单,必须拿 Base64 输出去核对;同一个哈希的十六进制表示和 Base64 表示是不同的字符串,所以选一个,坚持下去。

把大家伙切成小块编码

和解码器一样,编码器也是基于缓冲区的:读完整输入,发出完整输出。标准库里没有流式编码器,所以面对大载荷,计划就是内存,而这道算术有一种令人愉悦的对称性。编码让数据变大三分之一,所以最大的分配是输出 - 不是输入 - 对于一个 1 GB 的文件,你应该预期面前会摆着大约 1.33 GB 的文本。

如果一次拿不住这么多,你可以分块编码,因为 Base64 字母表在三字节边界上是自同步的:把每个 3 字节切片独立编码,拼接结果与整体编码完全相同:

require "base64"
require "securerandom"
bin = SecureRandom.random_bytes(10_001)
whole = Base64.strict_encode64(bin)
chunked = bin.scan(/.{1,3}/m).map { |slice| Base64.strict_encode64(slice) }.join
puts chunked == whole
# => true

同一个技巧还给你一个手工折行器,与 encode64 完全一致:45 个字节永远编码成恰好 60 个字符,所以在 45 字节处切分输入、用换行拼接各段,就能逐行复现经典的 MIME 输出,一次只有一个切片在内存里:

def wrap_like_encode64(bin)
  lines = bin.scan(/.{1,45}/m).map { |slice| Base64.strict_encode64(slice) }
  lines.join("\n") + "\n"
end
bin = SecureRandom.random_bytes(10_001)
puts wrap_like_encode64(bin) == Base64.encode64(bin)
# => true

从命令行

编码也不需要脚本文件。一行流形式读文件,把它的 Base64 写到 stdout:

ruby -rbase64 -e 'print Base64.strict_encode64(File.binread(ARGV[0]))' payload.bin > payload.b64

管道形式读 stdin,这是你包装任何命令字节流的方式:

some_command | ruby -rbase64 -e 'print Base64.strict_encode64(STDIN.read)'

两处都保留 print - 一个多余的 puts 会给你的 Base64 追加换行,对 strict_encode64 的输出而言,那会把一枚干净的令牌变成坏掉的。和解码侧一样的经验法则:如果你输出的下一个消费者是严格的,那么除 Base64 本身外,什么都不能跟着同行。

让 Ruby 开发者多付字节的陷阱

  • JSON 里的末尾换行。Base64.encode64 给每个非空结果以换行收尾,所以一个本应是干净令牌的值,会带着一个意外 \n 抵达你的 JSON 末尾。对任何要存储、比较或单行发送的东西,用 strict_encode64
  • 令牌和 URL 里的 60 字符折行。同一个方法会把长输出折成多行。URL 里一个折行的字符串是两个 URL,一枚折行的令牌是坏掉的。还是那句话:strict_encode64,或者如果你被 encode64 的输出绑住,就 strip/delete 掉换行。
  • URL 里的加号和斜杠。查询字符串里的标准 Base64 意味着出门时对 %2B%2F%3D 做百分号编码,然后指望对方解码它们。urlsafe_encode64 在源头消灭这个问题。
  • 填充放错了地方。JWT 和其他令牌方案要填充关闭;MIME 读取器可能受不了缺失的填充。只有当规范明确要求时才发出 padding: false,并且知道你的每个消费者站在那道围栏的哪一侧。
  • 字符不是字节。一个带一个重音字母的 5 字符字符串在 UTF-8 里是 6 字节,输出长度算术跑在字节上。当编码结果“太长”时,数字节,别数字符。
  • schema 设计里的三分之一税。一个 16 KB 的 BLOB 在 TEXT 列里变成大约 22 KB 的 Base64 字符串。按编码形式 - 而不是二进制形式 - 给你的列、缓存和 API 载荷定尺寸。
  • 两个字母表,两个不同的字符串。同样的字节在标准字母表和 URL 安全字母表里编码结果不同,所以一个编码值只能与同一字母表的另一个值比较。永远不要比较或混用它们。
  • Base64 不是锁。编码一个秘密不会让它变成秘密。任何拿到字符串的人都有你的数据;Base64 只控制字节看起来什么样,不控制谁能读它。

省下字节和 bug 的习惯

  • strict_encode64 设为默认。输出一旦要住进 URL、cookie 或标识符,立刻换成 urlsafe_encode64;只有目的地是邮件这类按行组织的文本协议时,才换成 encode64
  • 保持线路两端编码器和解码器的字母表一致。最常见的“Base64 坏了”bug,就是一个标准字母表的生产者遇到了 URL 安全的消费者,或者反过来。
  • 给编码器喂你打算编码的字节:文件用 File.binread,构造的二进制用 pack,字符串就是数据时用 UTF-8 字符串。编码器不会质疑你的选择 - 它只是数字节。
  • 给增长留预算。每当一个 Base64 字符串跨过边界进入有尺寸的容器,乘以 4/3,再给填充留一点余量。
  • 用 Base64 换可携带性,永远不要换保密性。如果目标是让数据保持私密,工具是加密,Base64 只是你对密文之后要做的事。

Base64 如何成为 gem

在生命的大部分时间里,Base64 模块只是标准库里的一个文件,和 Ruby 许多最老的助手一样。严格和 URL 安全方法在 1.9 开发线期间加入了原始的一对 - 整个 base64 库带着全部四个方法于 2008 年 9 月加入 trunk,首次在 1.9.1(2009 年)发货,padding: 关键字则在 2015 年随 Ruby 2.3 到来。到那时,你今天看到的 API 的一切都已经定型 - 剩下的故事是关于这个模块如何发货的。

2020 年,Ruby 3.0 到来,核心团队开始把标准库抽成自己的 gem,base64 成了其中之一:版本 0.1.0,由核心贡献者在 ruby/base64 仓库维护。它作为默认 gem发货 - 随 Ruby 分发、永远可用,所以 require "base64" 零仪式地继续工作。版本 0.2.0 在 2023 年随 Ruby 3.3 跟进,加入了 Base64::VERSION 常量和一套丰富得多的文档。

然后 2024 年 12 月的 Ruby 3.4 重画了线:base64 从默认 gem 列表挪到了捆绑 gem列表,与 csvdrb 同一层架子。捆绑 gem 仍然随语言发货,但基于 Bundler 的项目被期望声明它们,所以如果你在 Ruby 3.4 或更新版本上、应用由 Bundler 驱动,把 gem "base64" 加进 Gemfile(或运行 gem install base64)就齐了。2025 年的 Ruby 4.0 带来版本 0.3.0,加上 RBS 类型签名,让静态检查器能正眼看这个模块。

贯穿整个旅程,实现保持它一直以来的样子:几十行纯 Ruby,裹在核心 packunpack 模板外面。没有 C 扩展,没有依赖,而且 - 在 rubygems.org 上下载量以亿计 - 平台上安装量最大的 gem 之一。

有趣的 Ruby 事实

  • 整个模块,编码器在内,短到可以在一个咖啡休息里读完。encode64 字面就是 [bin].pack("m")strict_encode64[bin].pack("m0"),而 urlsafe_encode64 是严格编码器加上两个字符的替换,你要它去掉填充它就去掉。
  • encode64 的 60 字符折行既不匹配 MIME 的 76 字符上限,也不匹配 PEM 的经典 64。它只是 m pack 模板一向所做的,mail gem 的 Base64 编码器还赞许地评论它:Ruby 的自动折行让输出保持在 SMTP 限制之内。
  • Ruby 的 Net::HTTP 对 Basic 认证懒得用 Base64 模块 - 它直接调用 pack 模板,这是个不错的提醒:这个模块是核心之上的便利层,而不是反过来。
  • 每个摘要类都带着一个 base64digest 方法,所以 Digest::SHA256.base64digesthexdigest 旁边的头等公民 - 文本形式的校验和,不用第二次调用。
  • YAML 的 !binary 标签是乔装的 Base64。你一 dump 一个 BINARY 字符串,Psych 就做编码,这就是为什么装满二进制的配置文件长那样。
  • 你正在用的模块并不总像你记忆中的模块。老 Ruby 有 b64encode(按选定宽度折行)和 decode_b(RFC 2047 头解码);两者都在 1.9 线里消失了,所以你继承的任何调用它们的 2010 年之前的代码,都会死于 NoMethodError
  • YouTube 的视频 ID 是不带填充的 base64url - 11 个字符,无加号,无斜杠,无等号 - 恰恰是 URL 安全字母表被设计来处理的那种短小、链接安全的标识符。

另一面

现在你有了完整的编码图景:一匹从不让你意外的默认主力干将,一个为需要它的协议折行的经典,一个带填充开关的链接安全字母表,还有那些精确决定你的输出将长什么样的字节级规则。反方向 - 把一个 Base64 字符串拆开,在 Ruby 的三个解码器之间做选择,并把结果字节变成你能用的东西 - 有着它自己安静的陷阱,从一个从不说“不”的解码器开始。街道的那一侧,在下文链接的 Base64 解码文章里被深入覆盖。

最后更新: 2026-09-08

相关文章: Ruby 中的 Base64 解码:完整指南