언제 encodeURI / encodeURIComponent 대신 escape를 사용해야합니까?


1392

사용 할 때 - 쿼리 문자열을 인코딩 할 때 웹 서버로 전송하는 escape()과 할 때 사용 encodeURI()하거나 encodeURIComponent():

탈출을 사용하십시오 :

escape("% +&=");

또는

encodeURI () / encodeURIComponent () 사용

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

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

111
일반적인 사용 사례 encodeURIComponent("var1=value1&var2=value2")아니라는 점을 지적 할 가치가 있습니다. 이 예제는 =and 를 인코딩 할 것이며 &, 의도하지 않은 것입니다! encodeURIComponent일반적으로 각 키 값 쌍의 값 (각 뒤에있는 부분 =) 에만 별도로 적용됩니다 .
Timothy Shields

3
열쇠에 대해 무엇을해야합니까? 그 안에 =가 있으면 어떻게해야합니까?
Mala

3
@Mala 나는 여전히 일반적인 웹 프로그래밍에 익숙하지 않지만 제한된 경험에서 사용한 것은 키와 값을 별도로 인코딩하여 '='를 유지 var params = encodeURIComponent(key) + '=' + encodeURIComponent(value);하는 것입니다.
nedshares

1
@nedshares 나는 그것을 가지고 놀고 있었지만 키가 말할 수있는 한 적어도 같은 방식으로는 인코딩되지 않은 것 같습니다. 어쩌면 키에 =가있는 것이 사양에 위배됩니까?
Mala

1
또한 최신 JavaScript 구현은 URL 및 해당 쿼리 문자열을 조작하기위한 더 높은 수준의 인터페이스 URLURLSearchParam 을 제공한다는 점을 지적 할 가치가 있습니다.
Bart Robinson

답변:


1914

탈출()

사용하지 마십시오! escape()섹션 B.2.1.2 이스케이프에 정의되어 있으며 부록 B소개 텍스트 는 다음과 같습니다.

...이 부록에 명시된 모든 언어 기능과 동작은 하나 이상의 바람직하지 않은 특성을 가지며 레거시 사용이없는 경우이 사양에서 제거됩니다. ...
... 프로그래머는 새로운 ECMAScript 코드를 작성할 때 이러한 기능과 동작이 존재하거나 존재한다고 가정해서는 안됩니다.

행동:

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

@ * _ +-. /를 제외한 특수 문자는 인코딩됩니다.

코드 단위 값이 0xFF 이하인 문자의 16 진 형식은 두 자리 이스케이프 시퀀스 %xx입니다.

코드 단위가 더 큰 문자의 경우 4 자리 형식 %uxxxx이 사용됩니다. RFC3986에 정의 된대로 쿼리 문자열 내에서는 허용되지 않습니다 .

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

퍼센트 부호는 바로 뒤에 두 개의 16 진수가 오는 경우에만 허용되며 퍼센트 뒤에 오는 u것은 허용되지 않습니다.

encodeURI ()

작업 URL을 원할 때 encodeURI를 사용하십시오. 전화하세요 :

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

얻을 :

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

URL을 파괴하고 리턴하기 때문에 encodeURIComponent를 호출하지 마십시오

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

encodeURIComponent ()

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는 '문자를 이스케이프하지 않습니다 . 일반적인 버그는을 (를) 사용 href='MyUrl'하여 주입 버그가 발생할 수있는 html 속성을 만드는 것 입니다. 문자열에서 html을 생성하는 경우 속성 따옴표 "대신을 사용 '하거나 인코딩 레이어를 추가하십시오 ( '% 27로 인코딩 가능).

이러한 유형의 인코딩에 대한 자세한 내용은 다음을 확인하십시오. http://en.wikipedia.org/wiki/Percent-encoding


31
@Francois는 수신 서버에 따라 이스케이프가 상위 ASCII 문자 또는 비 ASCII 문자와 같은 이스케이프 인코딩 방식을 올바르게 디코딩하지 못할 수 있습니다. 예를 들어, Python의 FieldStorage 클래스는 이스케이프로 인코딩 된 경우 위 문자열을 올바르게 디코딩하지 않습니다.
Ray

22
@Francois escape ()는 문자, 숫자 및 *@-_+./를 제외한 하위 128 ASCII 문자를 인코딩하지만 unescape ()는 escape ()의 역입니다. 내가 알 수있는 한, 그들은 URL 인코딩을 위해 설계된 레거시 함수이며 여전히 이전 버전과의 호환성을 위해 구현되었습니다. 일반적으로 응용 프로그램 / 웹 서비스 / 등을 위해 설계된 응용 프로그램과 상호 작용하지 않는 한 사용해서는 안됩니다.
Anthony DiSanti

3
물론 URL을 URI 구성 요소로 전달하려는 경우가 아니라면 encodeURIComponent를 호출하십시오.
tom

4
작은 따옴표를 처리하지 않는 이유는 무엇입니까?
Eric

11
@Eric 작은 따옴표는 URI ( RFC-3986 ) 내에서 완전히 유효한 문자이므로 작은 따옴표를 인코딩하지 않습니다 . 작은 따옴표가 유효한 문자 가 아닌 HTML 내에 URI를 포함 시키면 문제가 발생합니다 . URI를도 (대체 할 것이다 "HTML 인코딩"인 것을, 다음, 다음 '으로 'HTML 문서에 배치되기 전에).
Lee

441

encodeURIComponent가 아닌 encodeURIComponent에 의해 인코딩 된 정확히 11 자 사이의 차이점은 다음 encodeURI()encodeURIComponent()같습니다.

encodeURI와 encodeURIComponent의 10 가지 차이점이있는 테이블

이 코드를 사용하여 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);


이 브라우저는 의존적이지 않습니까?
Pacerier

4
@bladnman encodeURI 및 encodeURIComponent는 모든 주요 브라우저에서이 방식으로 작동해야합니다. Chrome과 Firefox에서 위의 코드를 모두 console.table을 지원하므로 테스트 할 수 있습니다. 다른 브라우저 (Firefox 및 Chrome 포함)에서는 다음 코드를 사용할 수 있습니다.var arr=[]; for(var i=0;i<256;i++){var char=String.fromCharCode(i); if(encodeURI(char)!==encodeURIComponent(char)) console.log("character: "+char + " | encodeURI: " +encodeURI(char) + " |encodeURIComponent: " + encodeURIComponent(char) ) }
Johann Echavarria

1
@Pacerier :)
Johann Echavarria을

원래 사양이 너무 모호하지 않는 한 @Pacerier 다양한 브라우저에서 동일해야합니다 ... 또한 참조 stackoverflow.com/questions/4407599/...
크리스토프 후씨

2
이 여러 차례를 찬성해야합니다! 불행히도 한 번만 투표 할 수 있습니다.
Ramazan Polat

46

이 기사를 밝히는 것을 발견했습니다 : 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!

11
당신이 링크하는 기사에는 많은 넌센스가 포함되어 있습니다. 그것은 필자 자신이 그 기능이 무엇을 위해 올바르게 사용되는지 이해하지 못한 것 같습니다 ...
Christoph

2
@Christoph 그것은 나에게 합리적으로 보입니다. 특히, 나는 encodeURI그것이 매우 모호한 가장자리의 경우에만 유용하고 실제로 존재할 필요가없는 것처럼 보입니다. 나는 그와 약간의 의견 차이가 있지만 거기에 명백한 거짓이나 바보 같은 것이 보이지 않습니다. 넌센스 란 정확히 무엇이라고 생각하십니까?
Mark Amery

1
요소 의 enctype속성은 FORM서버에 제출하기 위해 양식 데이터 세트를 인코딩하는 데 사용되는 컨텐츠 유형을 지정합니다. application / x-www-form-urlencoded 기본 컨텐츠 유형입니다. 이 컨텐츠 유형으로 제출 된 양식은 다음과 같이 인코딩되어야합니다. [...] 공백 문자는 "+ '로 대체되고 [...] 영숫자가 아닌 문자는`% HH', [...]로 대체됩니다. Ref : HTML4 Sepc
cychoi

2
encodeURIComponent ( 'A + B'). replace (/ \ % 20 / g, '+') + '\ n'+ decodeURIComponent ( "A + % 2B + B".replace (/ \ + / g, '% 20' ));
Zlatin Zlatev

39

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 "";
}

5
또한 # (파운드 / 해시 / 숫자) 부호 (% 23)를 수행하지 않습니다.
xr280xr

1
@ xr280xr 무슨 뜻인가요? 에 encodeURIComponent는 23 % (? 어쩌면 2014 년에하지 않았다)에 인 코드 번호를 않습니다
데이비드 Balažic

38

encodeURI ()-escape () 함수는 HTTP가 아닌 자바 스크립트 이스케이프를위한 것입니다.


내가 같은 URL을 가지고 있다면 : var url = "http://kuler-api.adobe.com/rss/get.cfm?startIndex=0&itemsPerPage=20&timeSpan=0&listType=rating"... 그리고 나는 var gurl = "http://ajax.googleapis.com/ajax/services/feed/load?v=1.0&callback=?&q=" + url;다음 과 같이 Google Ajax API를 통해 액세스하고 싶습니다 : ... 그런 다음을 사용해야 escape(url)합니다. encodeURI(url)그런 매개 변수로는 작동하지 않습니다.
랜스 폴라드

15
유 ecnodeURIComponent (URL)를 사용한다
Ustaman 산갓

2
세 가지 기능 모두 문제가 있습니다. 작업을 수행하는 자체 기능을 작성하는 것이 좋습니다.
Jerry Joseph

17

작은 비교표 Java 대 JavaScript 대 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

12

이러한 방법 중 하나를 그대로 사용하지 않는 것이 좋습니다. 올바른 일을하는 자신의 함수를 작성하십시오.

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


1
(정말 실수하지 않고 크롬 가장자리와 파이어 폭스에서 호환되는 경우)
yan bellavance

10

또한 모두 서로 다른 문자 집합을 인코딩하고 필요한 문자를 선택합니다. encodeURI ()는 encodeURIComponent ()보다 적은 수의 문자를 인코딩합니다.이 코드는 escape ()보다 적은 수의 (또한 dannyp의 포인트와 다른) 문자를 인코딩합니다.


8

자바 스크립트를 인코딩하기 위해 세 가지 내장 함수가 제공되었습니다.

  1. escape()-인코딩하지 않음 @*/+ 이 방법은 ECMA 3 이후에는 더 이상 사용되지 않으므로 피해야합니다.

  2. encodeURI()-인코딩하지 않습니다 ~!@#$&*()=:/,;?+' . URI가 완전한 URI라고 가정하므로 URI에서 특별한 의미가있는 예약 문자는 인코딩하지 않습니다. 이 방법은 특수한 URL 세그먼트 대신 전체 URL을 변환하려는 경우에 사용됩니다. 예 encodeURI('http://stackoverflow.com'); -http: //stackoverflow.com

  3. encodeURIComponent()-인코딩하지 않음 - _ . ! ~ * ' ( ) 이 기능은 특정 문자의 각 인스턴스를 문자의 UTF-8 인코딩을 나타내는 1, 2, 3 또는 4 개의 이스케이프 시퀀스로 대체하여 URI (Uniform Resource Identifier) ​​구성 요소를 인코딩합니다. 이 메소드는 URL 구성 요소를 변환하는 데 사용해야합니다. 예를 들어 일부 사용자 입력을 추가해야합니다. 예-다음 encodeURIComponent('http://stackoverflow.com'); 을 제공합니다-http % 3A % 2F % 2Fstackoverflow.com

이 모든 인코딩은 UTF 8에서 수행됩니다. 즉 문자는 UTF-8 형식으로 변환됩니다.

encodeURIComponent는 encodeURI의 예약 문자 및 숫자 부호 #를 인코딩한다는 점에서 encodeURI와 다릅니다.


3

다양한 방법으로 실험하는 것이 다양한 용도와 기능을 잘 처리 한 후에도 좋은 위생 검사라는 것을 알았습니다.

이를 위해 나는 이 웹 사이트 가 내가 적절한 일을하고 있다는 의심을 확인하는데 매우 유용하다는 것을 알게되었습니다 . 또한 해석하기 어려울 수있는 encodeURIComponent의 문자열을 디코딩하는 데 유용한 것으로 입증되었습니다. 좋은 북마크 :

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


2

허용 된 답변이 좋습니다. 마지막 부분을 확장하려면

encodeURIComponent는 '문자를 이스케이프하지 않습니다. 일반적인 버그는 이것을 사용하여 href = 'MyUrl'과 같은 html 속성을 생성하는데, 이는 주입 버그를 겪을 수 있습니다. 문자열에서 HTML을 구성하는 경우 속성 따옴표에 '대신'를 사용하거나 인코딩 레이어를 추가하십시오 ( '는 27 %로 인코딩 가능).

안전을 유지하려면 예약되지 않은 문자를 인코딩하는 백분율도 인코딩 해야합니다.

이 방법을 사용하여 이스케이프 처리 할 수 ​​있습니다 (소스 Mozilla )

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

// fixedEncodeURIComponent("'") --> "%27"

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.log와 함께 console.table합니다 (예뻐 출력).


2

Johann의 테이블 에서 영감을 얻어 테이블 을 확장하기로 결정했습니다. 인코딩 할 ASCII 문자를 확인하고 싶었습니다.

console.table의 스크린 샷

표는 인코딩 된 문자 만 보여줍니다. 빈 셀은 원본과 인코딩 된 문자가 동일 함을 의미합니다.


추가로 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>

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;
};

4
@ChristianVielma escape ()는 더 이상 사용되지 않지만 w3schools.com을 참조하지 마십시오. w3fools.com 참조
Jerry Joseph

4
@Christian Vielma – 일부 는 W3Schools참조 자료논란의 여지적고 유용하다고 생각합니다 . 모든 사람이 W3Schools를 참조해서는 안된다는 데 동의하지는 않습니다.
DavidRR

2
W3Schools는 나쁜 랩을 얻습니다. 물론 그들은 항상 정확하지는 않지만 다시 한 번 잘못 된 블로그 게시물을 많이 보았습니다. 저에게 때때로 용어의 일부를 배우기위한 좋은 출발점이되고 나서 다른 자료를 조금 더 깊이 파고 들었습니다. 가장 중요한 것은 단일 자원이 이런 종류의 물건에 관해서는 절대 성경적이어서는 안된다는 것입니다.
ryandlf

@molokoloco는이 기능이 encodeURI존재하지 않지만 존재 하는 버전으로 대체 된 것으로 보입니다 escape.
SOFe
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.