Сжать строку на сервере Sql и распаковать на javascript - PullRequest
2 голосов
/ 22 марта 2020

Я хочу перенести длинную строку из моей базы данных на мою веб-страницу. Итак, я хочу попробовать метод сжатия моей строки на моем сервере и распаковать ее на стороне клиента.

Пока у меня есть это в моих sql кодах сервера:

select compress('this is just a sample string')

, которое возвращает это:

0x1F8B08000000000004002BC9C82C5600A2ACD2E212854485E2C4DC829C5485E292A2CCBC7400206D53921C000000

Теперь мне нужна функция в моем javascript чтобы отменить операцию сжатия:

var str = "0x1F8B08000000000004002BC9C82C5600A2ACD2E212854485E2C4DC829C5485E292A2CCBC7400206D53921C000000";
alert(decompressed(str));

, которая должна выдать предупреждение ", это просто пример строки ".

Ответы [ 4 ]

4 голосов
/ 24 марта 2020

Во-первых, позвольте мне объяснить разницу между тем, как VARBINARY (MAX) хранится и отображается в SSMS.
Строка "0x1F8B0800000000000 ..." - это шестнадцатеричное представление, создаваемое SSMS из varbinary данных, хранящихся в базе данных. Подчеркнутое двоичное значение состоит в основном из непечатаемых символов. Поэтому, если вы попытаетесь использовать эту строку в своем коде java, она просто не сможет работать напрямую.

Я создал здесь пример, если вы нажмете кнопку «STEP», вы увидите реальное значение: HexToBin

Вот почему ваш второй пример не будет работать, вам нужно прочитать байтовый массив из базы данных и затем использовать этот байтовый массив в zlib.

Есть хороший пример того, как использовать deflate в java: Java Распаковать строку, сжатую с помощью zlib deflate

2 голосов
/ 01 апреля 2020

Когда вы выполните этот запрос: select compress('this is just a sample string') (например, с помощью MS SQL Server Management Studio) Вы увидите текст представление в шестнадцатеричном формате двоичный сжатый текст.

Я провел тест с длинным текстом lorem ipsum , приведенным также как varchar и nvarchar (Вы можете заметить, что внутри этого текста нет двухбайтовые символы, но для этого примера это не имеет значения):

Этот сжатый длинный текст хранится в столбце varbinary(max) внутри MS SQL:

--------VARCHAR----------    --------NVARCHAR--------
Original     Hex   Binary    Original    Hex   Binary
   13046    4024     2011       13046   4748     2373

Таким образом, лучший выбор здесь - это передать из серверной части двоичные данные, , а не шестнадцатеричное представление.

Сообщите браузеру, что ответ получен в формате gzip. :

СТОРОНА СЕРВЕРА : Вот пример конечной точки в PHP:

<?php  /* getcompressed.php */
    header("Content-Encoding: gzip");
    header("Vary: Accept-Encoding");
    header("Content-type: text/html; charset=UTF-16"); /* nvarchar */
    $serverName = 'testserver';
    $connectionOptions = array('Database'=>'testdatabase');
    $conn = sqlsrv_connect($serverName, $connectionOptions);  
    $sql = 'SELECT compressed FROM tb_compression WHERE id = 1';
    $qry = sqlsrv_query($conn, $sql);
    $row = sqlsrv_fetch_array($qry);
    $compressed = $row[0];
    sqlsrv_close($conn);
    echo $compressed;
?>

СТОРОНА КЛИЕНТА : Вот рабочий фрагмент в JavaScript:

var request = new XMLHttpRequest();
request.onload = function(e) {
    var text = e.currentTarget.responseText;
    console.log(text); /* Here You go */
};
request.responseType = 'text';
request.open('GET', 'getcompressed.php', true);
request.send(null);

Это работает для меня в Chrome и FF также. Попробуйте это.

Использование gunzip javaScript Библиотека:

SERVER SIDE : Вот пример конечной точки в PHP:

<?php  /* getcompressed.php */
    header('Content-Type: application/octet-stream');
    $serverName = 'testserver';
    $connectionOptions = array('Database'=>'testdatabase');
    $conn = sqlsrv_connect($serverName, $connectionOptions);  
    $sql = 'SELECT compressed FROM tb_compression WHERE id = 1';
    $qry = sqlsrv_query($conn, $sql);
    $row = sqlsrv_fetch_array($qry);
    $compressed = $row[0];
    sqlsrv_close($conn);
    echo $compressed;
?>

СТОРОНА КЛИЕНТА : вот рабочий фрагмент в JavaScript:

КРЕДИТ: библиотека, используемая здесь для распаковки, gunzip.min. js от Имая Юта .

var request = new XMLHttpRequest();
request.onload = function(e) {
    var response = new Uint8Array(e.currentTarget.response);
    console.log(response.byteLength);
    /* Strip out the response termination */
    var compressed = response.subarray(0, response.byteLength - 4);
    var gunzip = new Zlib.Gunzip(compressed);
    var decompressed = gunzip.decompress();
    var encoding = 'utf-8'; /* For varchar text (ansi) */
    //var encoding = 'utf-16'; /* For nvarchar text (double-byte) */
    var text = new TextDecoder(encoding).decode(decompressed);
    console.log(text); /* Here You go */
};
request.responseType = 'arraybuffer';
request.open('GET', 'getcompressed.php', true);
request.send(null);

Если вы посмотрите на response.byteLength, для этого примера текста размером 13046 байт, вы будете убедитесь, что по сети эффективно передаются только байты 2015 года.

2 голосов
/ 30 марта 2020

Может быть, вы хотите что-то вроде этого: https://jsfiddle.net/58mgsy9a/

const parseString = str => {
    const strWithoutprefix = str.slice(2);
    const array = strWithoutprefix.match(/.{1,2}/g);
    return array.map(pair => parseInt(pair, 16));
};

const decompressed = gzipArray => {
    const gunzip = new Zlib.Gunzip(gzipArray);
    const plain = gunzip.decompress();
    return String.fromCharCode(...plain);
};

var str = "0x1F8B08000000000004002BC9C82C5600A2ACD2E212854485E2C4DC829C5485E292A2CCBC7400206D53921C000000";
alert(decompressed(parseString(str)));

Функция parseString берет вашу входную строку и преобразует ее в массив чисел, потому что zlib ожидает массив числа в качестве входа. Затем распакованная функция использует zlib для распаковки массива. Функция распаковки zlib возвращает массив чисел, поэтому мы конвертируем его обратно в строку.

2 голосов
/ 22 марта 2020

Поскольку @ Karl-Johan Sjögren заявил, что функция sql compress() возвращает значение GZIP, вы не сможете распаковать его на javascript без использования внешней библиотеки, такой как zlib .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...