我有一个 Web 应用程序(Ruby on Rails),它将一些 YAML 作为隐藏输入字段的值发送。现在我想要减小发送到浏览器的文本大小。什么是最有效的无损压缩形式,可以发送最少的数据?我可以承担服务器端压缩和解压缩的额外成本。
你可以使用 Ruby 核心中的 zlib 实现来压缩/解压数据:
require "zlib"
data = "some long yaml string" * 100
compressed_data = Zlib::Deflate.deflate(data)
#=> "x\x9C+\xCE\xCFMU\xC8\xC9\xCFKW\xA8L\xCC\xCDQ(.)\xCA\xCCK/\x1E\x15\x1C\x15\x1C\x15\x1C\x15\x1C\x15\x1C\x15\x1C\x15\x1C\x15D\x15\x04\x00\xB3G%\xA6"
您应该对压缩数据进行Base64编码,以使其可打印:
require 'base64'
encoded_data = Base64.encode64 compressed_data
#=> "eJwrzs9NVcjJz0tXqEzMzVEoLinKzEsvHhUcFRwVHBUcFRwVHBUcFUQVBACz\nRyWm\n"
接下来,在客户端,您可以使用pako(一个将zlib移植到JavaScript的库)来获取您的数据。 这个答案可能有助于您实现JS部分。
为了让您了解其有效性,以下是示例字符串的大小:
data.size # 2100
compressed_data.size # 48
encoded_data.size # 66
在客户端进行压缩并在服务器端进行解压缩时,同样的原理也适用。
Zlib::Inflate.inflate(Base64.decode64(encoded_data))
#=> "some long yaml stringsome long yaml str ... (shortened, as the string is long :)
免责声明:
ActiveSupport::Gzip
包装器,它允许对字符串进行gzip压缩/解压缩。compressed_log = ActiveSupport::Gzip.compress('large string')
=> "\x1F\x8B\b\x00yq5c\x00\x03..."
original_log = ActiveSupport::Gzip.decompress(compressed_log)
=> "large string"
在幕后,压缩方法使用 Zlib::GzipWriter
类来写入 gzip 文件。同样地,解压方法使用 Zlib::GzipReader
类来读取 gzip 文件。
Zlib::Deflate.deflate
方法的输出格式与gzip
命令行工具生成的格式不兼容,因此gunzip
不会接受它。gunzip
希望在压缩内容之前包含一些头数据。如果您想使用gunzip
读取输出,则可以使用以下代码:Zlib::Deflate.new(nil, 31).deflate(data, Zlib::FINISH)
。 - Guss