我怀疑这不是加密,但我找不到更好的词语了。我需要传递一个长的查询字符串,像这样:
http://test.com/test.php?key=[some_very_loooooooooooooooooooooooong_query_string]
查询字符串不包含敏感信息,所以在这种情况下我并不担心安全问题。只是...太长而且难看。是否有一个库函数可以让我将查询字符串编码/加密/压缩成类似于md5()结果的东西(类似于始终为32个字符的字符串),但可以解码/解密/解压缩?
我怀疑这不是加密,但我找不到更好的词语了。我需要传递一个长的查询字符串,像这样:
http://test.com/test.php?key=[some_very_loooooooooooooooooooooooong_query_string]
查询字符串不包含敏感信息,所以在这种情况下我并不担心安全问题。只是...太长而且难看。是否有一个库函数可以让我将查询字符串编码/加密/压缩成类似于md5()结果的东西(类似于始终为32个字符的字符串),但可以解码/解密/解压缩?
你可以尝试结合使用gzdeflate
(原始deflate格式)对数据进行压缩,然后使用base64_encode
仅使用那些不需要百分号编码的字符(另外将字符+
和/
替换为-
和_
):
$output = rtrim(strtr(base64_encode(gzdeflate($input, 9)), '+/', '-_'), '=');
反之亦然:
$output = gzinflate(base64_decode(strtr($input, '-_', '+/')));
这里有一个例子:
$input = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.';
// percent-encoding on plain text
var_dump(urlencode($input));
// deflated input
$output = rtrim(strtr(base64_encode(gzdeflate($input, 9)), '+/', '-_'), '=');
var_dump($output);
在这种情况下,节约约为23%。但是,此压缩过程的实际效率取决于您使用的数据。
这个基本前提很困难。在URL中传输任何值意味着您受限于ASCII字符子集。使用诸如gzcompress
的任何压缩都会减小字符串的大小,但会产生二进制blob。然而,不能使用该二进制blob在URL中进行传输,因为它会产生无效字符。为了使用ASCII字符子集传输该二进制blob,您需要以某种方式对其进行编码并将其转换为ASCII字符。
因此,您需要将ASCII字符转换为其他内容,然后再将其转换为ASCII字符。
但实际上,大多数情况下,您最初使用的ASCII字符已经是最优长度。以下是一个快速测试:
$str = 'Hello I am a very very very very long search string';
echo $str . "\n";
echo base64_encode(gzcompress($str, 9)) . "\n";
echo bin2hex(gzcompress($str, 9)) . "\n";
echo urlencode(gzcompress($str, 9)) . "\n";
Hello I am a very very very very long search string
eNrzSM3JyVfwVEjMVUhUKEstqkQncvLz0hWKUxOLkjMUikuKMvPSAc+AEoI=
78daf348cdc9c957f05448cc554854284b2daa442772f2f3d2158a53138b9233148a4b8a32f3d201cf801282
x%DA%F3H%CD%C9%C9W%F0TH%CCUHT%28K-%AAD%27r%F2%F3%D2%15%8AS%13%8B%923%14%8AK%8A2%F3%D2%01%CF%80%12%82
从中可以看出,原始字符串最短。在编码压缩中,Base64是最短的,因为它使用最大的字母表来表示二进制数据。但仍然比原始字符串长。
对于某些非常特定的字符组合和某些能够将其压缩为ASCII可表示数据的压缩算法,可能会实现一些压缩,但这更多是理论上的。 更新: 实际上,这听起来太消极了。问题在于需要确定压缩是否适用于您的用例。不同的数据具有不同的压缩方式和不同的编码算法。此外,较长的字符串可能会获得更好的压缩比。可能存在某个甜点,在那里可以实现一些压缩。您需要弄清楚自己大多数时间是否处于该甜点区域。
像 md5 这样的东西是不合适的,因为 md5 是一个哈希,这意味着它是不可逆的。您无法从中获取原始值。
如果无法通过URL发送参数,则只能通过POST方式发送。
这对我非常有效:
$out = urlencode(base64_encode(gzcompress($in)));
省很多钱。
$in = 'Hello I am a very very very very long search string' // (51)
$out = 64
$in = 500
$out = 328
$in = 1000
$out = 342
$in = 1500
$out = 352
字符串越长,压缩效果越好。压缩参数似乎没有任何影响。
urlencode(base64_encode(gzcompress($in)));
。我发现只有在字符串长度超过80个字符时才会出现压缩,例如从110到94。你在回答中没有很好地解释$in/$out变量。我想你是说这些是你的字符串输入/输出大小(压缩前/后)。这是我的答案,以你的答案为起点:http://stackoverflow.com/a/20915918/631764 - Buttle Butkusgzcompress()
不会有所帮助。例如,如果你采用 Pekka 的答案:gzcompress()
可以帮助你。但是这将导致出现不允许的字符,因此你将不得不再使用 urlencode()
(使字符串变长且难看)。urlencode()
处理,这可能对于非常小的字符串来说不太实用,但对于较大的字符串可能有效。 - Pekkasamplemail1@gmail.com,samplemail2@yahoo.com.ar,samplemail3@idontknowyou.com => samplemail1:1,samplemail2:5,samplemail3@idontknowyou:1
name=[TEXT 1]&phone=[PHONE]&mail=[MAIL]&desc=[TEXT 2]&create=[DATE 1]&modified=[DATE 2]&first=[NUMBER 1]&last=[NUMBER 2]
[TEXT1]|[PHONE]|[MAIL]|[TEXT 2]|[DATE 1]|[DATE 2]|[NUMBER 1][NUMBER 2]
[DATE 1][DATE 2][NUMBER 1][NUMBER 2][PHONE][MAIL]|[TEXT 1]|[TEXT 2]
3) 编码:
3.a) 虽然如果我们使用HTTP不支持的字符压缩编码,它们将被转换为更重的字符(如'año' => 'a%C3%B1o'),但仍然可以有用。也许您想将其压缩以存储在Unicode或二进制数据库中,或将其粘贴到网站(Facebook、Twitter等)上。
3.b) 尽管Base64[2]是一种很好的方法,但您可以通过使用用户函数而不是编译函数来牺牲速度来挤出更多的空间。
至少在Javascript的encodeURI()函数中,您可以使用任何这80个字符作为参数值而不会受到修改:
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.:,;+*-_/()$=!@?~'
虽然不是答案,但这里比较了各种建议的方法。
使用@Gumbo和@deceze的答案来比较我在GET请求中使用的相当长的字符串的长度。
<?php
$test_str="33036,33037,33038,38780,38772,37671,36531,38360,39173,38676,37888,36828,39176,39196,37321,36840,38519,37946,36543,39287,38989,38976,36804,38880,38922,38292,38507,38893,38993,39035,37880,38897,38378,36880,38492,38910,36868,38196,38750,37938,39268,38209,36856,36767,37936,36805,39248,36777,39027,39056,38987,38779,38919,38771,36851,38675,37887,38246,38791,38783,38661,37899,36846,36834,39263,37928,36822,37947,38992,38516,39177,38904,38896,37320,39217,37879,38293,38511,38774,37670,38185,37927,37939,38286,38298,38977,37891,38881,38197,38457,36962,39171,36760,36748,39249,39231,39191,36951,36963,36755,38769,38891,38654,38792,36863,36875,36956,36968,38978,38299,36743,36753,37896,38926,39270,38372,37948,39250,38763,38190,38678,36761,37925,36776,36844,37323,38781,38744,38321,38202,38793,38510,38288,36816,38384,37906,38184,38192,38745,39218,38673,39178,39198,39036,38504,36754,39180,37919,38768,38195,36850,38203,38672,38882,38071,39189,36795,36783,38870,38764,39028,36762,36750,38980,36958,37924,38884,37920,38877,36858,38493,36742,37895,36835,37907,36823,38762,38361,37937,38373,37949,36950,39202,38495,38291,36533,39037,36716,38925,37620,38906,37878,37322,38754,36818,39029,39264,38297,38517,36969,38905,36957,36789,36741,37908,38302,38775,39216,36812,38767,36845,36849,39181,39168,38671,39188,38490,36961,39201,36717,38382,38070,37868,38984,36770,38981,38494,36807,38885,36759,36857,38924,39038,38888,38876,36879,37897,36534,36764,37931,38254,39030,38990,37909,38982,38290,36848,37857,37923,38249,38658,38383,36813,36765,36817,37263,36769,37869,38183,36861,38206,39031,36800,36788,36972,38508,38303,39051,38491,38983,38759,36740,37958,36967,37930,39174,39182,36806,36867,36855,39222,37862,36752,38242,37965,38894,38182,37922,37918,36814,36872,38886,36860,36527,38194,38975,36718,39224,37436,39032";
echo(strlen($test_str)); echo("<br>");
echo(strlen(base64_encode(gzcompress($test_str,9)))); echo("<br>");
echo(strlen(bin2hex(gzcompress($test_str, 9)))); echo("<br>");
echo(strlen(urlencode(gzcompress($test_str, 9)))); echo("<br>");
echo(strlen(rtrim(strtr(base64_encode(gzdeflate($test_str, 9)), '+/', '-_'), '=')));
?>
Here are the results:
1799 (original length string)
928 (51.58% compression)
1388
1712
918 (51.028% compression)
使用gzcompress和base64_encode以及一些字符串转换可以获得可比较的结果。但是,gzdeflate似乎效率稍微更高一些
function _encode_string_array ($stringArray) {
$s = strtr(base64_encode(addslashes(gzcompress(serialize($stringArray),9))), '+/=', '-_,');
return $s;
}
function _decode_string_array ($stringArray) {
$s = unserialize(gzuncompress(stripslashes(base64_decode(strtr($stringArray, '-_,', '+/=')))));
return $s;
}
对于长/非常长的字符串值,您应该使用POST方法而不是GET!
为了获得良好的编码,您可以尝试urlencode()/urldecode()
或者htmlentities()/html_entity_decode()
还要注意,'%2F'在浏览器中被翻译为'/'字符(目录分隔符)。如果您只使用urlencode,您可能需要对其进行替换。
我不建议在GET参数上使用gzcompress。
base64_encode
函数可以将字符串编码为不可读的形式(当然也很容易解码),但是会使体积增加33%。
urlencode()
函数可以将URL中不适合的字符转换为它们的URL编码形式。如果你的目的是让字符串在URL中正常工作,那么这可能是正确的方法。
如果你有一个正在运行的会话,你也可以考虑将查询字符串放入一个带有随机(小)数字的会话变量中,并将该随机数放入GET字符串中。当然,这种方法只能在当前会话中生存。
请注意,由于服务器和浏览器的限制,GET字符串的大小不应超过1-2千字节。