I had to port the client part of a PHP based client-server program, which received some XML data along with compressed images as binary data. As it cost me some time to inflate the received data in Ruby, I want to share what I found out about deflating and inflating data in Ruby and PHP.
As you can easily find out in the comments of the PHP gzdeflate manual entry, gzdeflate is using raw deflate encoding. Another important thing to note is that “PHP deflate” is not the same as “HTTP deflate” as the HTTP uses the zlib format along with the deflate compression.
Before we come to the solution of the original problem of inflating data, we take a short look at deflating data in Ruby and PHP.
Deflate Data in Ruby for PHP Destination
If you want to compress data exactly the same way like PHP does (e.g. to be able to send it to a PHP app and inflate it there again), you can use the solution described by eden li:
def gzdeflate (s) Zlib::Deflate.new(nil, -Zlib::MAX_WBITS).deflate(s, Zlib::FINISH) end
Note the necessary (but nonintuitive) usage of -Zlib::MAX_WBITS which avoids generating some headers not used by PHP.
Inflate Data in Ruby From PHP Source
But what to do if you have data which was deflated by a PHP app? In PHP you would simply write:
With this piece of Ruby code you are able to extract binary data, which was compressed by a PHP application:
require 'base64' require 'zlib' open("5.jpg", "wb") do |file| file.write( Zlib::Inflate.new(-Zlib::MAX_WBITS).inflate( Base64.decode64(encoded_and_compressed_image) ) ) end
First, you have to decode the data using the Base64 class. Then pass the encoded data to the inflate method of Zlib::Inflate.
Again, you have to use the -Zlib::MAX_WBITS parameter when constructing the Inflate object.
The -Zlib::MAX_WBITS is necessary because PHP uses a raw deflate algorithm in the gzdeflate method but ruby defaults to either gzip or zlib (but NOT the raw deflate format).
One thought on “How to Inflate And Deflate Data in Ruby and PHP”
Nice article. I had to create a gzip (gzcat) compatible file and after some tinkering found that the following parameters will do:
windowBits = 15 + 16 # use largest window size (15) and gzip header (+16)
Zlib::Deflate.new(nil, windowBits).deflate(data, Zlib::FINISH)