簡體   English   中英

在Sql server中壓縮字符串並在javascript中解壓

[英]Compress string in Sql server and decompress in javascript

我想將一個長字符串從我的數據庫傳輸到我的網頁。 所以,我想嘗試在我的服務器中壓縮我的字符串並在客戶端解壓縮它的方法。

到目前為止,我的 sql server 代碼中有這個:

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

返回這個:

0x1F8B08000000000004002BC9C82C5600A2ACD2E212854485E2C4DC829C5485E292A2CCBC7400206D53921C000000

現在我需要在我的 javascript 中使用一個函數來恢復壓縮操作:

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

這應該提醒“這只是一個示例字符串”。

首先,讓我解釋一下 VARBINARY(MAX) 在 SSMS 中如何存儲和顯示的區別。
字符串“0x1F8B0800000000000...”是由存儲在數據庫中的 varbinary 數據的 SSMS 創建的十六進制表示。 下面的二進制值大多是不可打印的字符。 因此,如果您嘗試在 Java 代碼中使用此字符串,則它無法直接工作。

我在這里創建了一個例子,如果你按下“STEP”按鈕,你會看到真正的價值: HexToBin

這就是為什么你的第二個例子不起作用,你需要從數據庫中讀取字節數組,然后在 zlib 中使用這個字節數組。

有一個很好的例子如何在 java 中使用 deflate: Java Decompress a string compression with zlib deflate

也許你想要這樣的東西: 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 的解壓縮函數返回一個數字數組,因此我們將其轉換回字符串。

當您運行此查詢時: select compress('this is just a sample string') (例如使用 MSSQL Server Management Studio)您將看到二進制壓縮文本的十六進制格式的文本表示。

我用一個lorem ipsum長文本進行了測試,該文本也被轉換為varcharnvarchar (您可能會注意到,在該文本中沒有雙字節字符,但對於本示例來說無關緊要):

這個壓縮的長文本存儲在 MSSQL 的varbinary(max)列中:

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

所以,這里最好的選擇是從后端傳輸二進制數據,而不是十六進制表示。

告訴瀏覽器響應已被壓縮:

服務器端:這是 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 庫:

服務器端:這是 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.jsImaya裕太

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 字節有效地通過網絡傳輸。

正如@Karl-Johan Sjögren 所說,sql 函數compress()返回一個 GZIP 值,如果不使用zlib等外部庫,您將無法在 javascript 上解壓縮它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM