Должен ли я использовать encodeURI или encodeURIComponent для кодирования URL?

282

Какой из этих двух методов следует использовать для кодирования URL?

Адитья Шукла
источник
3
Также см stackoverflow.com/a/3608791/632951
Pacerier
13
Одно существенное отличие состоит в том, что encodeURIкодирование не будет выполняться /так: encodeURIComponent("ac/dc")=> ac%2Fdcи encodeURI("ac/dc")=>ac/dc
Это может быть полезно: "encodeURIComponent() and encodeURI() encode a URI by replacing URL reserved characters with their UTF-8 encoding....They differ because encodeURI does not encode queryString or hash values...URLs do not allow many special characters, like spaces or slashes. However these special characters are part of life, so URL encoding was invented." Источник
user1063287
Также смотрите специальный раздел под названием по encodeURIComponent differs from encodeURI as followsадресу: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
user1063287

Ответы:

324

Это зависит от того, что вы действительно хотите сделать.

encodeURI предполагает, что ввод является полным URI, который может содержать некоторые символы, для которых требуется кодировка.

encodeURIComponent закодирует все со специальным значением, поэтому вы используете его для компонентов URI, таких как

var world = "A string with symbols & characters that have special meaning?";
var uri = 'http://example.com/foo?hello=' + encodeURIComponent(world);
Quentin
источник
108

Если вы кодируете строку для добавления в компонент URL (параметр строки запроса), вам следует вызвать encodeURIComponent.

Если вы кодируете существующий URL, позвоните encodeURI.

SLaks
источник
1
Если я использую AJAX, как мне декодировать URL-адрес, который передается в PHP?
Адитья Шукла
6
Вы не Веб-сервер делает это автоматически.
Квентин,
@Aditya: Это зависит от того, что вы делаете.
SLaks
@slaks. Я передаю параметры через get, поэтому я хочу получить их в php.
Адитья Шукла
2
Хорошо. Я мог бы сказать немного поспешно, когда сказал, что веб-сервер сделает это, но любая библиотека, которую вы используете для чтения данных формы, позаботится об этом за вас.
Квентин
47

У xkr.us отличная дискуссия с примерами. Чтобы процитировать их резюме:

Метод escape () не кодирует символ +, который интерпретируется как пробел на стороне сервера, а также генерируется формами с пробелами в их полях. Из-за этого недостатка и того факта, что эта функция не может правильно обрабатывать символы, не входящие в ASCII, вы должны по возможности избегать использования escape (). Лучшей альтернативой обычно является encodeURIComponent ().

escape () не будет кодировать: @ * / +

Использование метода encodeURI () немного более специализировано, чем escape (), поскольку он кодирует URI, а не строку запроса, являющуюся частью URL. Используйте этот метод, когда вам нужно закодировать строку, которая будет использоваться для любого ресурса, который использует URI и которому необходимо, чтобы определенные символы оставались незашифрованными. Обратите внимание, что этот метод не кодирует символ ', поскольку он является допустимым символом в URI.

encodeURI () не будет кодировать: ~! @ # $ & * () =: /,;? + '

Наконец, метод encodeURIComponent () должен использоваться в большинстве случаев при кодировании одного компонента URI. Этот метод будет кодировать определенные символы, которые обычно распознаются как специальные символы для URI, так что многие компоненты могут быть включены. Обратите внимание, что этот метод не кодирует символ ', поскольку он является допустимым символом в URI.

encodeURIComponent () не будет кодировать: ~! * () '

BrianFreud
источник
Недавно узнал. Серверы TOMCAT 9 более подробно рассказывают о том, что вы можете отправить по URL. encodeURIComponent () работает лучше в тех случаях, когда у вас есть «пробелы» в том, что вам нужно для кодирования. Tomcat 8 не заботился, но 9 более конкретен.
Агги Джон 87
Другими словами, происходит encodeURIсбой, если вы пытаетесь преобразовать имя файла в URL и имя файла содержится #в нем
gman
17

Вот краткое изложение.

  1. escape () не будет кодировать @ * _ + -. /

    Не используйте это.

  2. encodeURI () не будет кодировать AZ az 0-9; /? : @ & = + $ - _. ! ~ * '() #

    Используйте его, когда вы вводите полный URL-адрес, например « https://searchexample.com/search?q=wiki »

  3. encodeURIComponent () не будет кодировать AZ az 0-9 - _. ! ~ * '() Используйте его, когда ваш ввод является частью полного URL, например const queryStr = encodeURIComponent(someString)
Фрэнк Ван
источник
1
Это отличный ответ, потому что он точно говорит, что они делают. Однако у меня все еще есть вопрос о том, что мне следует использовать и когда. Что если мой URI-компонент является полным URL? Должен ли я затем использовать Правило 2 или Правило 3 сверху ИЛИ, возможно, ОБА, как encodeURIComponent (encodeURI (theCompleteURI))
Panu Logic
10

encodeURIComponent (): предполагает, что его аргумент является частью (такой как протокол, имя хоста, путь или строка запроса) URI. Поэтому он избегает знаков препинания, которые используются для разделения частей URI.

encodeURI (): используется для кодирования существующего URL

Гопал
источник
7

Разница между encodeURIи encodeURIComponent:

encodeURIComponent(value)в основном используется для кодирования значений параметров queryString и кодирует каждый применимый символ в value. encodeURIигнорирует префикс протокола ( http://) и имя домена.


В очень, очень редких случаях, когда вы хотите реализовать ручное кодирование для кодирования дополнительных символов (хотя их не требуется кодировать в типичных случаях), таких как:, ! *тогда вы можете использовать:

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

( источник )

T.Todua
источник
6
Вы не должны избегать этих символов в URL.
Arashsoft
Как сказано в цитируемой документации: «эти символы не имеют формализованного использования для разграничения URI»
caesarsol
@caesarsol так, я должен отредактировать свой ответ. дайте мне знать ваши мысли, потому что я не могу понять, что означает эта приведенная документация ..
T.Todua
просто бесполезно кодировать эти символы, если только вы не делаете что-то из обычных
сценариев
2

Другие ответы описывают цели. Вот символы, которые каждая функция на самом деле преобразует :

control = '\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F'
        + '\x10\x11\x12\x13\x14\X15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F'
                                                                    + '\x7F'
encodeURI         (control + ' "%<>[\\]^`{|}'                             )
encodeURIComponent(control + ' "%<>[\\]^`{|}' + '#$&,:;=?' + '+/@'        )
escape            (control + ' "%<>[\\]^`{|}' + '#$&,:;=?' +       "!'()~")

Все вышеперечисленные символы преобразуются в шестнадцатеричные коды процента. Пробел до %20, процент до %25и т. Д. Символы ниже проходят без изменений.

Вот символы, которые функции НЕ будут преобразовывать :

pass_thru = '*-._0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'

encodeURI         (pass_thru + '#$&,:;=?' + '+/@' + "!'()~")
encodeURIComponent(pass_thru +                      "!'()~")
escape            (pass_thru +              '+/@'          )
Боб Стейн
источник
-4

Как правило, используйте encodeURIComponent. Не бойтесь длинного имени, думая, что оно более конкретно в его использовании, для меня это наиболее часто используемый метод. Также не впадайте в использование encodeURI, потому что вы проверили его, и он, кажется, правильно кодирует, вероятно, это не то, что вы хотели использовать, и хотя ваш простой тест с использованием «Fred» в поле первого имени сработал, вы обнаружите, что позже, когда вы будете использовать более сложный текст, такой как добавление амперсанда или хэштега, произойдет сбой. Вы можете посмотреть на другие ответы по причинам, почему это так.

Helzgate
источник