1472

编码要发送到 Web 服务器的查询字符串时 - 您何时使用escape()以及何时使用encodeURI()or encodeURIComponent()

使用转义:

escape("% +&=");

或者

使用 encodeURI() / encodeURIComponent()

encodeURI("http://www.google.com?var1=value1&var2=value2");

encodeURIComponent("var1=value1&var2=value2");
4

15 回答 15

1980

逃脱()

不要使用它! 在B.2.1.2escape()节中定义了转义,附件 B的介绍文本说:

... 本附件中规定的所有语言特征和行为都有一个或多个不受欢迎的特征,在没有遗留使用的情况下,将从本规范中删除。...
... 程序员在编写新的 ECMAScript 代码时不应使用或假设存在这些特性和行为......

行为:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/escape

特殊字符被编码,除了:@*_+-./

字符的十六进制形式,其代码单元值为 0xFF 或更小,是一个两位数的转义序列:%xx.

对于具有更大代码单元的字符,使用四位数格式%uxxxx。这在查询字符串中是不允许的(在RFC3986中定义):

query       = *( pchar / "/" / "?" )
pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
pct-encoded   = "%" HEXDIG HEXDIG
sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
              / "*" / "+" / "," / ";" / "="

百分号仅在直接后跟两个十六进制数字时才允许使用,不允许百分号后跟u

编码URI()

如果您想要一个工作 URL,请使用 encodeURI。拨打此电话:

encodeURI("http://www.example.org/a file with spaces.html")

要得到:

http://www.example.org/a%20file%20with%20spaces.html

不要调用 encodeURIComponent ,因为它会破坏 URL 并返回

http%3A%2F%2Fwww.example.org%2Fa%20file%20with%20spaces.html

请注意,与 encodeURIComponent 一样,encodeURI 不会转义 ' 字符。

编码URIComponent()

如果要对 URL 参数的值进行编码,请使用 encodeURIComponent。

var p1 = encodeURIComponent("http://example.org/?a=12&b=55")

然后你可以创建你需要的 URL:

var url = "http://example.net/?param1=" + p1 + "&param2=99";

你会得到这个完整的 URL:

http://example.net/?param1=http%3A%2F%2Fexample.org%2F%Ffa%3D12%26b%3D55&param2=99

请注意,encodeURIComponent 不会转义'字符。一个常见的错误是使用它来创建 html 属性,例如href='MyUrl',这可能会遭受注入错误。如果您从字符串构造 html,请使用"而不是'for 属性引号,或者添加额外的编码层('可以编码为 %27)。

有关此类编码的更多信息,您可以查看:http ://en.wikipedia.org/wiki/Percent-encoding

于 2010-08-31T12:04:17.180 回答
475

encodeURI()和之间的区别encodeURIComponent()恰好是由 encodeURIComponent 编码但不是由 encodeURI 编码的 11 个字符:

encodeURI 和 encodeURIComponent 的十个区别表

我使用以下代码在 Google Chrome 中使用console.table轻松生成了此表:

var arr = [];
for(var i=0;i<256;i++) {
  var char=String.fromCharCode(i);
  if(encodeURI(char)!==encodeURIComponent(char)) {
    arr.push({
      character:char,
      encodeURI:encodeURI(char),
      encodeURIComponent:encodeURIComponent(char)
    });
  }
}
console.table(arr);

于 2014-05-24T06:54:51.143 回答
47

我发现这篇文章很有启发性: Javascript Madness: Query String Parsing

当我试图理解为什么 decodeURIComponent 没有正确解码“+”时,我发现了它。这是一个摘录:

String:                         "A + B"
Expected Query String Encoding: "A+%2B+B"
escape("A + B") =               "A%20+%20B"     Wrong!
encodeURI("A + B") =            "A%20+%20B"     Wrong!
encodeURIComponent("A + B") =   "A%20%2B%20B"   Acceptable, but strange

Encoded String:                 "A+%2B+B"
Expected Decoding:              "A + B"
unescape("A+%2B+B") =           "A+++B"       Wrong!
decodeURI("A+%2B+B") =          "A+++B"       Wrong!
decodeURIComponent("A+%2B+B") = "A+++B"       Wrong!
于 2012-10-09T09:26:43.437 回答
41

encodeURIComponent 不编码-_.!~*'(),导致在 xml 字符串中将数据发布到 php 时出现问题。

例如:
<xml><text x="100" y="150" value="It's a value with single quote" /> </xml>

一般逃生用encodeURI
%3Cxml%3E%3Ctext%20x=%22100%22%20y=%22150%22%20value=%22It's%20a%20value%20with%20single%20quote%22%20/%3E%20%3C/xml%3E

可以看到,单引号没有编码。为了解决问题,我创建了两个函数来解决我的项目中的问题,用于编码 URL:

function encodeData(s:String):String{
    return encodeURIComponent(s).replace(/\-/g, "%2D").replace(/\_/g, "%5F").replace(/\./g, "%2E").replace(/\!/g, "%21").replace(/\~/g, "%7E").replace(/\*/g, "%2A").replace(/\'/g, "%27").replace(/\(/g, "%28").replace(/\)/g, "%29");
}

对于解码 URL:

function decodeData(s:String):String{
    try{
        return decodeURIComponent(s.replace(/\%2D/g, "-").replace(/\%5F/g, "_").replace(/\%2E/g, ".").replace(/\%21/g, "!").replace(/\%7E/g, "~").replace(/\%2A/g, "*").replace(/\%27/g, "'").replace(/\%28/g, "(").replace(/\%29/g, ")"));
    }catch (e:Error) {
    }
    return "";
}
于 2013-05-08T07:51:13.737 回答
36

encodeURI() - escape() 函数用于 javascript 转义,而不是 HTTP。

于 2008-09-16T19:26:22.293 回答
18

小型比较表 Java vs. JavaScript vs. PHP。

1. Java URLEncoder.encode (using UTF8 charset)
2. JavaScript encodeURIComponent
3. JavaScript escape
4. PHP urlencode
5. PHP rawurlencode

char   JAVA JavaScript --PHP---
[ ]     +    %20  %20  +    %20
[!]     %21  !    %21  %21  %21
[*]     *    *    *    %2A  %2A
[']     %27  '    %27  %27  %27 
[(]     %28  (    %28  %28  %28
[)]     %29  )    %29  %29  %29
[;]     %3B  %3B  %3B  %3B  %3B
[:]     %3A  %3A  %3A  %3A  %3A
[@]     %40  %40  @    %40  %40
[&]     %26  %26  %26  %26  %26
[=]     %3D  %3D  %3D  %3D  %3D
[+]     %2B  %2B  +    %2B  %2B
[$]     %24  %24  %24  %24  %24
[,]     %2C  %2C  %2C  %2C  %2C
[/]     %2F  %2F  /    %2F  %2F
[?]     %3F  %3F  %3F  %3F  %3F
[#]     %23  %23  %23  %23  %23
[[]     %5B  %5B  %5B  %5B  %5B
[]]     %5D  %5D  %5D  %5D  %5D
----------------------------------------
[~]     %7E  ~    %7E  %7E  ~
[-]     -    -    -    -    -
[_]     _    _    _    _    _
[%]     %25  %25  %25  %25  %25
[\]     %5C  %5C  %5C  %5C  %5C
----------------------------------------
char  -JAVA-  --JavaScript--  -----PHP------
[ä]   %C3%A4  %C3%A4  %E4     %C3%A4  %C3%A4
[ф]   %D1%84  %D1%84  %u0444  %D1%84  %D1%84
于 2015-10-08T15:20:20.967 回答
13

我建议不要按原样使用其中一种方法。编写你自己的函数来做正确的事情。

MDN 给出了一个很好的 url 编码示例,如下所示。

var fileName = 'my file(2).txt';
var header = "Content-Disposition: attachment; filename*=UTF-8''" + encodeRFC5987ValueChars(fileName);

console.log(header); 
// logs "Content-Disposition: attachment; filename*=UTF-8''my%20file%282%29.txt"


function encodeRFC5987ValueChars (str) {
    return encodeURIComponent(str).
        // Note that although RFC3986 reserves "!", RFC5987 does not,
        // so we do not need to escape it
        replace(/['()]/g, escape). // i.e., %27 %28 %29
        replace(/\*/g, '%2A').
            // The following are not required for percent-encoding per RFC5987, 
            //  so we can allow for a little better readability over the wire: |`^
            replace(/%(?:7C|60|5E)/g, unescape);
}

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent

于 2014-04-23T16:54:17.263 回答
10

出于编码 javascript 的目的,它提供了三个内置函数 -

  1. escape()- 不编码@*/+ 此方法在 ECMA 3 之后已弃用,因此应避免使用。

  2. encodeURI()- 不编码~!@#$&*()=:/,;?+' 它假定 URI 是一个完整的 URI,因此不对 URI 中具有特殊含义的保留字符进行编码。当意图转换完整的 URL 而不是某些特殊的 URL 段时,使用此方法。示例 -encodeURI('http://stackoverflow.com'); 将给出 - http://stackoverflow.com

  3. encodeURIComponent()- 不编码 - _ . ! ~ * ' ( ) 此函数通过将某些字符的每个实例替换为表示字符的 UTF-8 编码的一个、两个、三个或四个转义序列来对统一资源标识符 (URI) 组件进行编码。此方法应用于转换 URL 的组件。例如,需要附加一些用户输入示例 -encodeURIComponent('http://stackoverflow.com'); 将给出 - http%3A%2F%2Fstackoverflow.com

所有这些编码都以 UTF 8 执行,即字符将转换为 UTF-8 格式。

encodeURIComponent 与 encodeURI 的不同之处在于它对保留字符和数字符号 # of encodeURI 进行编码

于 2017-04-21T07:55:51.573 回答
9

还要记住,它们都对不同的字符集进行编码,并适当地选择您需要的字符集。encodeURI() 编码的字符比 encodeURIComponent() 编码的字符少,而 encodeURIComponent() 编码的字符比 escape() 编码的字符少(而且在 dannyp 的观点上也不同)。

于 2008-09-16T19:40:32.850 回答
5

只是尝试encodeURI()encodeURIComponent()你自己...

console.log(encodeURIComponent('@#$%^&*'));

输入:@#$%^&*。输出:%40%23%24%25%5E%26*。所以,等等,发生了什么事*?为什么没有转换?如果您尝试这样做,肯定会导致问题linux command "$string"。TLDR:您实际上想要fixedEncodeURIComponent()fixedEncodeURI()。很长的故事...

何时使用encodeURI() 绝不。 encodeURI()在括号编码方面未能遵守 RFC3986。按照MDN encodeURI() 文档fixedEncodeURI()中的定义和进一步说明使用...

function fixedEncodeURI(str) {
   return encodeURI(str).replace(/%5B/g, '[').replace(/%5D/g, ']');
}

何时使用encodeURIComponent() 绝不。 encodeURIComponent()在编码方面未能遵守 RFC3986!'()*:. 按照MDN encodeURIComponent() 文档fixedEncodeURIComponent()中的定义和进一步说明使用...

function fixedEncodeURIComponent(str) {
 return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
   return '%' + c.charCodeAt(0).toString(16);
 });
}

然后您可以使用fixedEncodeURI()对单个 URL 片段进行编码,而fixedEncodeURIComponent()将对 URL 片段和连接器进行编码;或者,简单地说,fixedEncodeURI()不会编码+@?=:#;,$&(作为常见的 URL 运算符),但&会。+fixedEncodeURIComponent()

于 2020-06-17T18:48:06.950 回答
3

我发现尝试各种方法是一种很好的健全性检查,即使在很好地掌握了它们的各种用途和功能之后也是如此。

为此,我发现这个网站非常有用,可以证实我的怀疑,即我正在做一些适当的事情。它还被证明对解码编码URIComponent 的字符串很有用,这可能很难解释。一个很棒的书签:

http://www.the-art-of-web.com/javascript/escape/

于 2013-08-08T12:34:09.147 回答
3

接受的答案很好。扩展最后一部分:

请注意,encodeURIComponent 不会转义 ' 字符。一个常见的错误是使用它来创建 html 属性,例如 href='MyUrl',这可能会遭受注入错误。如果您从字符串构造 html,请使用 " 而不是 ' 作为属性引号,或者添加额外的编码层(' 可以编码为 %27)。

如果您想安全起见,也应该对未保留字符的百分比编码进行编码。

您可以使用此方法来逃避它们(来源Mozilla

function fixedEncodeURIComponent(str) {
  return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
    return '%' + c.charCodeAt(0).toString(16);
  });
}

// fixedEncodeURIComponent("'") --> "%27"
于 2017-09-27T06:56:16.080 回答
3

受到Johann 表的启发,我决定扩展表。我想看看哪些 ASCII 字符被编码。

console.table 的截图

var ascii = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";

var encoded = [];

ascii.split("").forEach(function (char) {
    var obj = { char };
    if (char != encodeURI(char))
        obj.encodeURI = encodeURI(char);
    if (char != encodeURIComponent(char))
        obj.encodeURIComponent = encodeURIComponent(char);
    if (obj.encodeURI || obj.encodeURIComponent)
        encoded.push(obj);
});

console.table(encoded);

表仅显示编码字符。空单元格表示原始字符和编码字符相同。


只是为了额外,我正在为urlencode()vs添加另一个表rawurlencode()。唯一的区别似乎是空格字符的编码。

console.table 的截图

<script>
<?php
$ascii = str_split(" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~", 1);
$encoded = [];
foreach ($ascii as $char) {
    $obj = ["char" => $char];
    if ($char != urlencode($char))
        $obj["urlencode"] = urlencode($char);
    if ($char != rawurlencode($char))
        $obj["rawurlencode"] = rawurlencode($char);
    if (isset($obj["rawurlencode"]) || isset($obj["rawurlencode"]))
        $encoded[] = $obj;
}
echo "var encoded = " . json_encode($encoded) . ";";
?>
console.table(encoded);
</script>
于 2019-02-11T11:56:19.273 回答
2

@johann-echavarria 答案的现代重写:

console.log(
    Array(256)
        .fill()
        .map((ignore, i) => String.fromCharCode(i))
        .filter(
            (char) =>
                encodeURI(char) !== encodeURIComponent(char)
                    ? {
                          character: char,
                          encodeURI: encodeURI(char),
                          encodeURIComponent: encodeURIComponent(char)
                      }
                    : false
        )
)

或者,如果您可以使用表格,请替换console.logconsole.table(用于更漂亮的输出)。

于 2018-02-09T01:45:03.073 回答
1

我有这个功能...

var escapeURIparam = function(url) {
    if (encodeURIComponent) url = encodeURIComponent(url);
    else if (encodeURI) url = encodeURI(url);
    else url = escape(url);
    url = url.replace(/\+/g, '%2B'); // Force the replacement of "+"
    return url;
};
于 2013-06-21T12:39:51.527 回答