【问题标题】:Encoding image data as UTF-8 string with gzip compression使用 gzip 压缩将图像数据编码为 UTF-8 字符串
【发布时间】:2012-10-29 21:05:56
【问题描述】:

我正在尝试将文件中的图像数据作为 base64 字符串存储到 PostgreSQL 数据库中,该字符串由 gzip 压缩以节省空间。我正在使用以下代码对图像进行编码:

@file = File.open("#{Rails.root.to_s}/public/" << @ad_object.image_url).read
@base64 = Base64.encode64(@file)
@compressed = ActiveSupport::Gzip.compress(@base64)
@compressed.force_encoding('UTF-8')
@ad_object.imageData = @compressed

当我尝试保存对象时,出现以下错误:

ActiveRecord::StatementInvalid (PG::Error: ERROR:  invalid byte sequence for encoding "UTF8": 0x8b

在 rails 控制台中,任何 gzip 压缩都将数据输出为 ASCII 8 位编码。我尝试将我的内部和外部编码设置为 UTF-8,但结果没有改变。如何将此压缩数据转换为 UTF-8 字符串?

【问题讨论】:

  • 首先,您是否要对已压缩的编码进行编码?第二个 base64 完全包含在 ASCII 中,而 ASCII 本身包含在 UTF-8 中。您不需要将其编码为 UTF-8。
  • 你有理由这样做吗? PostgreSQL 可以直接将二进制数据存储在bytea 列中,JPEG 和PNG 等常见图像格式不值得gzip-ing;我尝试尽可能少地分层附加编码,在这种情况下为零。
  • 如果您确实需要这样做,请在应用 Base64 编码之前应用压缩(如果值得的话)。压缩数据将不是有效的 UTF-8,除非可能是偶然的。
  • 图像是使用 CarrierWave gem 上传然后读取的。压缩的原因是因为图像数据将被发送到设备,我想尽量减少发送的数据量。我尝试了压缩,然后是 base64 编码,但生成的字符串是压缩前编码的两倍。
  • Base64 将比二进制文件大得多。它仅在通过文本协议(如用于电子邮件的 smtp)传输数据时有用

标签: ruby-on-rails postgresql


【解决方案1】:

由于多种原因,这没有多大意义。

  1. gzip 是二进制编码。绝对没有必要对某些内容进行 base64 编码然后对其进行 gzip 压缩,因为输出是二进制的,并且 base64 仅用于通过非 8bit-clean 协议进行传输。直接gzip文件就好了。

  2. 大多数图像数据已经使用 PNG 或 JPEG 等编解码器进行压缩,在图像数据压缩方面比 gzip 更有效。压缩它通常会使图像稍微大一点。对于图像数据,Gzip 永远不会像 loss-les PNG 格式那样高效,因此如果您的图像数据未压缩,PNG 会对其进行压缩而不是 gzip。

  3. 在表示二进制数据时,实际上并没有文本编码问题,因为它不是文本。它将不是有效的 utf-8,试图告诉系统它只会导致更多问题。

完全取消 base64 编码和 gzip 步骤。正如 mu 太短所说,只需使用 Rails binary 字段,让 Rails 处理二进制数据的编码和发送。

只需使用数据库中的bytea 字段并直接存储PNG 或JPEG 图像。这些在传输线上进行了十六进制编码,占用了二进制空间的 2 倍,但它们以二进制形式存储在磁盘上。如果 bytea 字段从压缩中受益,PostgreSQL 会自动压缩磁盘上的字段,但大多数图像数据不会。

要最小化图像的大小,请选择适当的压缩格式,例如PNG 用于无损压缩或JPEG 用于照片。在压缩之前尽可能多地对图像进行下采样,并使用产生可接受质量的最强压缩(对于 JPEG 等有损编解码器)。不要尝试使用 gzip/LZMA/etc 进一步压缩图像,它会一事无成。

当十六进制转义通过网络传输时,您的数据大小仍然会增加一倍。解决这个问题需要使用 PostgreSQL 二进制协议(困难且复杂)或二进制干净的边带来传输图像数据。如果 Pg gem 支持 SSL 压缩,您可以使用它来压缩协议流量,这将大大降低 hex 转义的成本。

如果需要将大小保持在绝对最小值,我不会使用 PotsgreSQL 有线协议将图像发送到设备。它的设计旨在提高性能和可靠性,而不是绝对最小尺寸。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-09
    • 1970-01-01
    • 2014-01-18
    • 2011-08-27
    • 2011-08-18
    • 2013-12-15
    相关资源
    最近更新 更多