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

What is the correct way to encodeURIcomponent non utf-8 characters and decodes them accordingly?

本文关键字:解码 是什么 方法 utf-8 组件 URI 字符 编码      更新时间:2023-09-26

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

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

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

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

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

  • http://ued.taobao.com/blog/2011/08/26/encode-war/
  • http://www.ruanyifeng.com/blog/2010/02/url_encoding.html

对于您的情况,%C8%B7%B6%A8实际上是从 GB2312 形式的''u786e'u5b9a'生成的。这通常发生在(旧版?(IE和FF版本上,当用户直接在地址栏中输入中文字符时,

或者您正在使用来自页面内容的非标准链接,该链接根本不执行 IRI 到 URI 编码,而只是像 '/tag/'xc8'xb7'xb6'xa8' 一样呈现二进制字符串(douban.com 曾经对标签有这种用法,现在他们使用 UTF8 中的正确 URI 编码(。不太确定,因为无法在Chrome中重现,也许在FF和IE中进行测试,关于豆瓣的部分是真的。

实际上,encodeURIComponent的正确输出应该是

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

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

此外,您可以在客户端签入以再次对包含 XX 大于 0x7F%XX的值应用encodeURIComponent。不过,我不太确定这是否针对 RFC 2396。

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

使用 escape() 然后将字符转换为数字字符引用,然后再将它们发送到服务器。

来自 MDN escape(( 参考:

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

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

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>';
?>