gpt4 book ai didi

ruby - 为什么 Ruby Base64 编码转换会丢失数据以及我如何进行路由?

转载 作者:太空宇宙 更新时间:2023-11-03 16:23:40 25 4
gpt4 key购买 nike

我正在构建一个与 Grape API 对话的 Rails UI。这是该程序的第二个实例。第一个实例运行良好。然而,第二个实例的 Grape API 似乎在通过网络发送之前破坏了数据。

我需要从 file > json > http > db 获取图像。现在我通过发送文件来做到这一点:文件 > 字符串 > 编码为 url-safe base64 > to_json > http > 解码 > 使用 ActiveRecord 保存到 sqlite3 db。根据以下内容,我将图像数据转换为 base64,导致我相信图像数据已损坏。但是,由于 Grape 都是 JSON,因此必须在发送之前对字符进行编码(因为,至少就 Ruby 的 JSON 库而言,无效的 UTF-8 == 无效的 JSON)。

所以我要么必须知道:

  1. 如何允许 Grape API 发送非 JSON(原始文件字符串)或
  2. 如何解码字符串并避免错误信息

打开文件并将其内容转换为 url 安全的 Base64。

File.open("#{folder}/#{file_name}", "rb:UTF-8") do |image|
file_as_string = image.read
end
=> "iVBORw0K ... # truncated for length

事情马上变得很奇怪。 IRB 执行预期的操作 - 编码为 UTF-8。

file_as_string.encoding.name
=> "UTF-8"

但是。服务器记录 ASCII-8BIT。我无法解释这一点。每个文件的顶部都有 Ruby 神奇的 UTF-8 注释。 Linux $LANG 设置为 en_US.UTF-8

好的,但是当 Base64 转换时,无论如何我都失去了情节。即使在 IRB 中,从 UTF-8 开始,它也会隐蔽。为什么是 US-ASCII?无论如何,为什么兼容性会丢失?

Base64.urlsafe_encode64(file_as_string).encoding.name
=> "US-ASCII"
Base64.urlsafe_decode64(Base64.urlsafe_encode64(file_as_string)).encoding.name
=> "ASCII-8BIT"
Base64.urlsafe_decode64(Base64.urlsafe_encode64(file_as_string)).encode("UTF-8")
Encoding::UndefinedConversionError: "\x89" from ASCII-8BIT to UTF-8
from (irb):27:in `encode'
from (irb):27
from /home/me/.rvm/rubies/ruby-2.2.1/bin/irb:11:in `<main>'

请注意,IRB 中的错误与我 a) 在 Grape 尝试 to_json 之前不对字符串进行 base64 编码和 b) 当我尝试解码并调用 .save 字符串时相同到 Rails 端的模型属性。

文件本身是二进制的(如果这很重要?)

$ file -bi /path/to/file.png
image/png; charset=binary

我尝试过或不愿意尝试的解决方案:

发送原始图像.read

这是一个 JSON API,因此 Grape 在通过网络发送数据之前转换为 JSON——这意味着任何响应都必须是有效的 JSON,据我所知。如果我尝试发送原始字符串,自动调用的 .to_json 会抛出相同的错误。

对结果进行强制编码

输出不是可读的 png。

降级

原始实例是 Ruby 1.9.2 和 CentOS 6.3。新实例是 Ruby 2.2.1 和 CentOS 7。我通常致力于向前发展,所以我宁愿开发一些解决方案,即使不向后兼容,然后回滚 Ruby 和我的操作系统。

不使用 UTF-8

Rails 的 config/application.rb 有一行 config.encoding = "utf-8"config/environment.rb 有行 Encoding.default_external = Encoding::UTF_8; Encoding.default_internal = Encoding::UTF_8 我希望不必为了这个问题而放弃 UTF-8 兼容性。


那么有没有办法绕过 to_json 调用直接在 Grape 中提供文件?或者对于 JSON-ing 和通过 http 发送是否有不同的安全编码?

最佳答案

PNG 文件没有字符编码。您应该在不声明字符编码的情况下打开文件。即使经过 base64 编码,您也无需关心字符集。

一旦文件被 base64 编码,结果就是 7 位 ASCII 字符串,因此 encoding.name 报告 “US-ASCII”。这是您应该传递给您的框架的字符串,

不要在 base64 编码之前对字符串调用 .encode() - 这肯定会损坏字符串。

澄清一下:

  1. file_as_string 既不是 UTF-8 也不是 ASCII。它没有字符编码,因为它是二进制文件。 file_as_string.encoding.name 与您无关。
  2. Base64.urlsafe_encode64(file_as_string).encoding.name = "US-ASCII" 是正确的,因为您通过将二进制文件编码为 base64 有效地将其转换为文本/字符串。这确实有字符编码 - 7 位 ASCII。这就是您应该传递给 Grape 以进行传输的内容。
  3. Base64.urlsafe_decode64(Base64.urlsafe_encode64(file_as_string)).encoding.name 是无关紧要的,因为结果又是一个二进制 字符串。 它没有字符编码。尝试 .encode() 这会破坏数据。
  4. 您的 IRB 失败是因为您要求 Ruby 将二进制字符串转换为 UTF-8 文本编码。这就像拍照并要求将其转换为法语。

关于ruby - 为什么 Ruby Base64 编码转换会丢失数据以及我如何进行路由?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29543326/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com