Используя php-gzdeflate и pako-js

Я пытаюсь объединить php-gzdeflate и pako. чтобы сжать строку я использую:

const compressed = ' <?php echo base64_encode(gzdeflate('Compress me')); ?> ' ;
// compressed now contains: c87PLShKLS5WyE0FAA==

но я не могу прочитать эту строку обратно, используя Пако. я пробовал следующее:

var enc = new TextEncoder("utf-8");
pako.ungzip(enc.encode(compressed) );

я получаю это сообщение обратно: необнаруженная неправильная проверка заголовка

Есть ли простой способ сжатия с использованием generic-php и раздувать с помощью pako?

до сих пор я пытался добавить различные "уровни" gzdeflate от одного до девяти, но ни один из них, кажется, не имеет никакого значения. и на данный момент, я просто догадываюсь.

и мы не будем устанавливать какие-либо специальные расширения для php, если это возможно

большое спасибо вам.

4 ответа

Обновив ответ @edwardsmarkf, вы можете решить эту проблему без использования функции atos. Большинство новых браузеров имеют API TextDecoder. Вы можете использовать это так:

const decoder = new TextDecoder();
const result = decoder.decode(pako.ungzip(atob(compressedBase64Data)));

Я не мог получить здесь ответы на работу, поэтому провел небольшое исследование.

Как PleaseStandКак указано здесь, проблема в том, что PHP использует строки UTF-8, а JS использует строки UTF-16. Следовательно, двоичная строка в кодировке строки base64 будет отличаться.

Решение, которое я использовал, - заставить JS интерпретировать данные как UTF-8. Это просто, так какpako принимает и возвращает Uint8Arrays, которые по сути являются строками UTF-8:

Сжать в JS, распаковать в 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

Сжать в PHP, распаковать в 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

Примечание: Buffer экземпляры также Uint8Arrayэкземпляров, поэтому нам не нужно преобразовыватьBuffer к Uint8Array прежде чем отдать его пако.

Эти функции также совместимы с языками:

//JS
console.log(decompress(compress('asdfasdfasdfasdf'))); //asdfasdfasdfasdf
//PHP
echo decompress(compress('asdfasdfasdfasdf')); //asdfasdfasdfasdf

Для JS это работает из коробки в NodeJs. В среде браузера вам понадобится полифил дляBuffer.

Для PHP не забудьте установить Zlib расширение.

Я не знаком с php, поэтому я как бы боролся с этой проблемой, поэтому я решил опубликовать минимальное рабочее решение на php:

      $response = gzdeflate('My data', 9, ZLIB_ENCODING_DEFLATE);

header('Content-Encoding: deflate');
echo $response;

После этого не нужно использовать pako, данные будут распакованы браузером.

Пример, если вы запрашиваете данные в формате json:

      $.ajax({
    type: 'GET',
    url: 'http://target.com',
    dataType: "json",
    contentType: "application/json; charset=utf-8",
    headers : {'Accept-Encoding': 'deflate '},
})
.done(function(res) {
    console.log(res)
})
.fail(function(xhr, textStatus, errorThrown) {
});

Это похоже на работу (ниже)

Шаги вовлечены:

серверная часть (php):

1) gzdeflate с использованием опции ZLIB_ENCODING_DEFLATE

2) base64_encode

клиентская сторона: (jScript)

1) атоб

2) pako.ungzip

3) функция atos

<script src='//cdnjs.cloudflare.com/ajax/libs/pako/1.0.5/pako_deflate.js' type='text/javascript'></script>

<script type='text/javascript'>
const compressedDEFLATE = '<?php echo base64_encode(gzdeflate('Compress me', 6, ZLIB_ENCODING_DEFLATE )); ?>'  ;

function atos(arr) {
    for (var i=0, l=arr.length, s='', c; c = arr[i++];)
        s += String.fromCharCode(
            c > 0xdf && c < 0xf0 && i < l-1
                ? (c & 0xf) << 12 | (arr[i++] & 0x3f) << 6 | arr[i++] & 0x3f
            : c > 0x7f && i < l
                ? (c & 0x1f) << 6 | arr[i++] & 0x3f
            : c
        );
    return s
}
    alert ( atos(pako.ungzip( atob(compressedDEFLATE)  ) )  );
</script>
Другие вопросы по тегам