Используя 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
принимает и возвращает Uint8Array
s, которые по сути являются строками 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>