I couldn't get the answers here to work, so I did some research.
As PleaseStand
pointed out here, the problem is that PHP uses UTF-8 strings, while JS uses UTF-16 strings. Hence, the binary string to base64 string encoding will differ.
The solution I used is to force JS to interpret the data as UTF-8. This is straightforward, as pako
accepts and returns Uint8Array
s, which are essentially UTF-8 strings.:
Compress in JS, Decompress in PHP:
//JS
const pako = require('pako');
const compress = str => Buffer.from(pako.deflateRaw(str)).toString('base64');
console.log(compress('asdfasdfasdfasdf')); //SyxOSUtEwgA=
//PHP
function decompress($str) { return gzinflate(base64_decode($str)); }
echo decompress('SyxOSUtEwgA='); //asdfasdfasdfasdf
Compress in PHP, Decompress in JS:
//PHP
function compress($str) { return base64_encode(gzdeflate($str, 9)); }
echo compress('asdfasdfasdf'); //SyxOSUuEYgA=
//JS
const pako = require('pako');
const decompress = str => pako.inflateRaw(Buffer.from(str, 'base64'), {to: 'string'});
console.log(decompress('SyxOSUuEYgA=')); //asdfasdfasdfs
Note: Buffer
instances are also Uint8Array
instances, hence we don't need to convert the Buffer
to a Uint8Array
before giving it to pako.
These functions are also compatible within the languages:
//JS
console.log(decompress(compress('asdfasdfasdfasdf'))); //asdfasdfasdfasdf
//PHP
echo decompress(compress('asdfasdfasdfasdf')); //asdfasdfasdfasdf
For JS, this works out of the box in NodeJs. In a browser environment, you will need a polyfil for Buffer
.
For PHP, remember to install the Zlib
extension.