编码URI组件非utf-8字符并对其进行相应解码的正确方法是什么?

时间:2012-04-28 09:09:01

标签: javascript utf-8 urldecode encodeuricomponent

我有一个Javascript书签,使用encodeURIcomponent将当前页面的URL传递给服务器端,然后在服务器端使用urldecode来获取字符。

问题是,当编码字符不在utf-8中时(对于我的情况,它是gb2312,但它可能是其他东西),并且当服务器执行urldecode时,解码后的字符变为正方形。显然,这不是编码之前的样子。

这是一个书签,输入可以是任何东西,所以我不能只在js中定义“encode as gb2312”,或者在php脚本中定义“解码为gb2312”。

那么,是否有正确的方法使用encodeURIcomponent将字符编码与内容一起传递,然后解码可以选择正确的编码来解码它?

2 个答案:

答案 0 :(得分:0)

对于浏览器的编码,特别是对于GB2312字符集,首先检查以下文档(中文)

对于您的情况,%C8%B7%B6%A8实际上是从'\u786e\u5b9a'的GB2312格式生成的。当用户在位置栏中直接输入中文字符时,这通常发生在(遗留?)版本的IE和FF上 你正在使用页面内容中的非标准链接,它根本不执行IRI到URI编码,只渲染二进制字符串,如'/tag/\xc8\xb7\xb6\xa8'(douban.com曾经有过对于标签的这种用法,现在他们在UTF8中使用了正确的URI编码。)不太确定,因为无法在Chrome中重现,也许在FF和IE中测试,部分关于douban是真的。

实际上,encodeURIComponent的正确输出应为

> encodeURIComponent('%C8%B7%B6%A8')
  "%25C8%25B7%25B6%25A8"

因此在服务器端,当一个不带引号的字符串包含非ascii字节时,你最好保持字符串不变,这里是'%C8%B7%B6%A8'

此外,您可以检查客户端是否再次对包含encodeURIComponent的值的%XX进行检查,其中XX大于0x7F。我不太确定这是否反对RFC 2396。

写英文好累啊,不过还是要入乡随俗〜

答案 1 :(得分:0)

使用escape(),然后在将字符发送到服务器之前将其翻译为numeric character reference

来自MDN escape() reference

  

字符的十六进制形式,其代码单元值为0xFF或   less,是一个两位数的转义序列:%xx。对于有角色的角色   更大的代码单元,使用四位数格式的%uxxxx。

因此,通过使用简单的escape()语句,可以很容易地将replace()的输出转换为数字字符引用:

escape(input_value).replace(/%u([0-9a-fA-F]{4})/g, '&#x$1;');

或者,如果您的服务器端语言仅支持十进制实体,请使用:

escape(input_value).replace(/%u([0-9a-fA-F]{4})/g, function(m0, m1) {
                return '&#' + parseInt(m1, 16) + ';';
};

PHP中的示例代码

client.html (文件编码:GB2312)

<html>
  <head>
    <meta charset="gb2312">
    <script>
    function processForm(form) {
        console.log('BEFORE:', form.test.value);
        form.test.value = escape(form.test.value).replace(/%u(\w{4})/g, function(m0, m1) {
            return '&#' + parseInt(m1, 16) + ';';
        });
        console.log('AFTER:', form.test.value);
        return true;
    }
    </script>
  </head>
  <body>
    <form method="post" action="server.php" onsubmit="return processForm(this);">
      <input type="text" name="test" value="确定">
      <input type="submit">
    </form>
  </body>
</html>

server.php

<?php
echo '<script>console.log("', 
     $_REQUEST['test'], ' --> ', 
     mb_decode_numericentity($_REQUEST['test'], array(0x80, 0xffff, 0, 0xffff), 'UTF-8'),
     '");</script>';
?>