【问题标题】:Unable to return binary data from rails API无法从 rails API 返回二进制数据
【发布时间】:2020-10-15 07:58:05
【问题描述】:

我已使用 rails 中的 binary 数据类型将 base64url_encoded 字符串存储到 postgres 数据库中。这是迁移

def change
  add_column :gmail_attachments, :base64_data, :binary
end

我存储的数据是来自gmail API 的base64 url​​ 编码字符串。当我尝试在 postgres 中将数据存储为 string 数据类型时,我得到了

ArgumentError(字符串包含空字节)

所以,我选择了二进制数据类型,并将其成功存储到数据库中。现在,当我尝试时

render status: 200, json: gmail_attachment_record

我收到以下错误

Encoding::UndefinedConversionError ("\xFF" 从 ASCII-8BIT 到 UTF-8):

如何消除此错误并返回存储的数据?我是否将其存储在错误的数据类型中?要实现这一点,rails ActiveRecord 数据类型的最佳选择是什么?

【问题讨论】:

标签: ruby-on-rails postgresql activerecord gmail-api


【解决方案1】:

当您保存带有 :binary 列的模型时,Rails 会为您完成所有工作,确保正确设置编码以确保您的数据正确持久化。

我相信您遇到了编码错误,因为to_json 方法(通过render 隐式调用)正试图通过JSON.encode 将您的二进制字符串转换为UTF-8。这就是您收到 UndefinedConversionError 的原因。 (ASCII-8BIT 是 ruby​​ 中的一种特殊编码,本质上意味着 BINARY。)


要进入工作状态,我想你会想要:

  • 将您的数据保存到二进制列,就像您在上面所做的一样 - 考虑将其命名为 data。 (更好的是,使用 ActiveStorage 并将其保存到其他地方的文件中。)我建议您首先将数据从 base64 转换为原始二进制表示:
# Not sure what the api exactly looks like, but you get the idea
require('base64')

base64_data = Gmail.get_attachment(...)

gmail_attachment.data = Base64.decode64(base64_data) # now our data field is just the raw bytes.
gmail_attachment.save
  • 然后您需要将其序列化回 base64 以便通过 to_json 传输。您可以通过 as_json 方法来做到这一点,如下所示:
# models/gmail_attachment.rb
require('base64')

class GmailAttachment < ApplicationRecord

  def base64_data
    Base64.encode64(self.data)
  end
end

# controllers/your_controller.rb
render json: gmail_attachment_record.as_json(except: [:data], methods: [:base64_data])

很确定这会让你朝着正确的方向前进!

【讨论】:

  • 感谢 Mark G。它运行良好。但是,我在编写的实际代码中遇到了语法问题。请在此处查看我的错误代码0bin.net/paste/…
  • 我现在可以返回数据,但看起来它不是我打算存储的形式。我收到的数据是 ASCII-8BIT(即二进制,我仍然使用 Base64.decode64(..) 对其进行解码吗?)我尝试了解码和不解码,当我从 db 读取它并使用 base64 编码时它没有真正采取它应该是的形式。我验证了这将在线编码器/解码器,并且我得到的数据与它应该在的地方相差甚远,
  • 很高兴听到它几乎可以工作了。我以为 Gmail API 返回了 base64 编码的数据?如果是这种情况,您需要在将其持久保存到数据库时对其进行解码,正如我上面建议的那样。当您通过 Rails 控制器发送它时,您需要对其进行编码。你有一个显示差异的例子吗?很高兴查看 gist/pastebin。
  • 请看这里,它包含实际图像的 URL 和我从 Gmail API 收到的 Gmail 附件数据。 0bin.net/paste/…
猜你喜欢
  • 1970-01-01
  • 2016-07-03
  • 2015-07-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-18
相关资源
最近更新 更多