3

假设为了提高存储效率,您已经使用 Zlib 压缩了不常访问的数据库数据,并且有人使用浏览器请求了其中的一些数据。人们将如何处理这些数据?

这是我想要的一个不切实际但直截了当的例子:

require "zlib"

class SomeController < ApplicationController

  def index
    compressed_data = Zlib::Deflate.deflate("Some precompressed database data.")
    render :text => compressed_data
  end
end

这会将压缩数据提供给客户端的浏览器,但不会将其解压缩以进行正确查看。有没有办法使这项工作,以便客户端以未压缩(膨胀)状态接收此数据。关键是我不想在控制器中充气,只是为了再次使用Rack::Deflater. 我想避免不必要的 cpu 使用/时间消耗,同时降低存储和带宽使用。

4

1 回答 1

2

为了使这成为可能,您首先需要将Content-Encoding标题设置为gzip. 而不是使用Zlib::Deflate.deflate你会想要创建一个新的StringIO缓冲区对象,将它传递给一个Zlib::GzipWriter对象,并通过它写入StringIO缓冲区对象。完成后,关闭Zlib::GzipWriter对象。最后,渲染出缓冲区的字符串。

例如:

require "zlib"
require "stringio"

class SomeController < ApplicationController

  def index
    response.headers["Content-Encoding"] = "gzip"

    buffer = StringIO.new

    gz = Zlib::GzipWriter.new(buffer, Zlib::DEFAULT_COMPRESSION, Zlib::DEFAULT_STRATEGY)
    gz.write("Some precompressed database data.")
    gz.close

    render :text => buffer.string
  end
end

或者,ActiveSupport::Gzip显然有一个内置的类方法,可以让你用更少的代码完成同样的事情。

class SomeController < ApplicationController

  def index
    response.headers["Content-Encoding"] = "gzip"

    string = ActiveSupport::Gzip.compress("Some precompressed database data.")

    render :text => string
  end
end

后一个示例将在 Rails 环境或包含该ActiveSupport框架的其他环境中工作,并且基本上是前一个示例的包装器,如果您无权访问ActiveSupport::Gzip.

于 2013-10-16T18:11:03.703 回答