Вопрос

У меня есть приложение, которое отправляет запрос POST в программное обеспечение форума VB и регистрирует кого-либо (без установки файлов cookie или чего-либо еще).

Как только пользователь входит в систему, я создаю переменную, которая создает путь на его локальном компьютере.

c: empfolder\date\username

Проблема в том, что некоторые имена пользователей выдают исключение "Недопустимые символы".Например, если мое имя пользователя было mas|fenix это вызвало бы исключение..

Path.Combine( _      
  Environment.GetFolderPath(System.Environment.SpecialFolder.CommonApplicationData), _
  DateTime.Now.ToString("ddMMyyhhmm") + "-" + form1.username)

Я не хочу удалять его из строки, но папка с их именем пользователя создается через FTP на сервере.И это подводит к моему второму вопросу.Если я создаю папку на сервере, могу ли я оставить в ней "недопустимые символы"?Я спрашиваю об этом только потому, что сервер основан на Linux, и я не уверен, принимает ли Linux это или нет.

Редактировать:Похоже, что кодирование URL-адреса - это НЕ то, чего я хочу..Вот что я хочу сделать:

old username = mas|fenix
new username = mas%xxfenix

Где %xx - значение ASCII или любое другое значение, которое позволило бы легко идентифицировать символ.

Это было полезно?

Решение

Редактировать:Обратите внимание, что этот ответ теперь устарел.Видишь Ответ Сергея Кучука ниже для лучшего исправления

UrlEncoding будет делать то, что вы предлагаете здесь.С C # вы просто используете HttpUtility, как уже упоминалось.

Вы также можете регулярно выражать недопустимые символы, а затем заменять, но это становится намного сложнее, так как вам нужно будет иметь некоторую форму конечного автомата (switch ...регистр, например), чтобы заменить правильными символами.С тех пор как UrlEncode делает это заранее, это довольно просто.

Что касается Linux по сравнению с Windows, есть некоторые символы, приемлемые в Linux, которых нет в Windows, но я бы не стал беспокоиться об этом, поскольку имя папки может быть возвращено путем декодирования строки URL, используя UrlDecode, так что вы можете обойти изменения в обе стороны.

Другие советы

Я экспериментировал с различными методами, которые .NET предоставляет для кодирования URL.Возможно, следующая таблица будет полезна (в качестве выходных данных тестового приложения, которое я написал).:

Unencoded UrlEncoded UrlEncodedUnicode UrlPathEncoded EscapedDataString EscapedUriString HtmlEncoded HtmlAttributeEncoded HexEscaped
A         A          A                 A              A                 A                A           A                    %41
B         B          B                 B              B                 B                B           B                    %42

a         a          a                 a              a                 a                a           a                    %61
b         b          b                 b              b                 b                b           b                    %62

0         0          0                 0              0                 0                0           0                    %30
1         1          1                 1              1                 1                1           1                    %31

[space]   +          +                 %20            %20               %20              [space]     [space]              %20
!         !          !                 !              !                 !                !           !                    %21
"         %22        %22               "              %22               %22              "      "               %22
#         %23        %23               #              %23               #                #           #                    %23
$         %24        %24               $              %24               $                $           $                    %24
%         %25        %25               %              %25               %25              %           %                    %25
&         %26        %26               &              %26               &                &       &                %26
'         %27        %27               '              '                 '                '       '                %27
(         (          (                 (              (                 (                (           (                    %28
)         )          )                 )              )                 )                )           )                    %29
*         *          *                 *              %2A               *                *           *                    %2A
+         %2b        %2b               +              %2B               +                +           +                    %2B
,         %2c        %2c               ,              %2C               ,                ,           ,                    %2C
-         -          -                 -              -                 -                -           -                    %2D
.         .          .                 .              .                 .                .           .                    %2E
/         %2f        %2f               /              %2F               /                /           /                    %2F
:         %3a        %3a               :              %3A               :                :           :                    %3A
;         %3b        %3b               ;              %3B               ;                ;           ;                    %3B
<         %3c        %3c               <              %3C               %3C              &lt;        &lt;                 %3C
=         %3d        %3d               =              %3D               =                =           =                    %3D
>         %3e        %3e               >              %3E               %3E              &gt;        >                    %3E
?         %3f        %3f               ?              %3F               ?                ?           ?                    %3F
@         %40        %40               @              %40               @                @           @                    %40
[         %5b        %5b               [              %5B               %5B              [           [                    %5B
\         %5c        %5c               \              %5C               %5C              \           \                    %5C
]         %5d        %5d               ]              %5D               %5D              ]           ]                    %5D
^         %5e        %5e               ^              %5E               %5E              ^           ^                    %5E
_         _          _                 _              _                 _                _           _                    %5F
`         %60        %60               `              %60               %60              `           `                    %60
{         %7b        %7b               {              %7B               %7B              {           {                    %7B
|         %7c        %7c               |              %7C               %7C              |           |                    %7C
}         %7d        %7d               }              %7D               %7D              }           }                    %7D
~         %7e        %7e               ~              ~                 ~                ~           ~                    %7E

Ā         %c4%80     %u0100            %c4%80         %C4%80            %C4%80           Ā           Ā                    [OoR]
ā         %c4%81     %u0101            %c4%81         %C4%81            %C4%81           ā           ā                    [OoR]
Ē         %c4%92     %u0112            %c4%92         %C4%92            %C4%92           Ē           Ē                    [OoR]
ē         %c4%93     %u0113            %c4%93         %C4%93            %C4%93           ē           ē                    [OoR]
Ī         %c4%aa     %u012a            %c4%aa         %C4%AA            %C4%AA           Ī           Ī                    [OoR]
ī         %c4%ab     %u012b            %c4%ab         %C4%AB            %C4%AB           ī           ī                    [OoR]
Ō         %c5%8c     %u014c            %c5%8c         %C5%8C            %C5%8C           Ō           Ō                    [OoR]
ō         %c5%8d     %u014d            %c5%8d         %C5%8D            %C5%8D           ō           ō                    [OoR]
Ū         %c5%aa     %u016a            %c5%aa         %C5%AA            %C5%AA           Ū           Ū                    [OoR]
ū         %c5%ab     %u016b            %c5%ab         %C5%AB            %C5%AB           ū           ū                    [OoR]

Столбцы представляют кодировки следующим образом:

  • UrlEncoded ( Кодированный URL ): HttpUtility.UrlEncode

  • UrlEncodedUnicode UrlEncodedUnicode: HttpUtility.UrlEncodeUnicode

  • UrlPathEncoded Закодированный: HttpUtility.UrlPathEncode

  • EscapedDataString ( экранированный параметр ): Uri.EscapeDataString

  • Избегающий управления: Uri.EscapeUriString

  • HtmlEncoded Закодированный: HttpUtility.HtmlEncode

  • HtmlAttributeEncoded Закодированный: HttpUtility.HtmlAttributeEncode

  • Шестиугольник: Uri.HexEscape

Примечания:

  1. HexEscape может обрабатывать только первые 255 символов.Поэтому он выдает ArgumentOutOfRange исключение для латинских A-расширенных символов (например, A).

  2. Эта таблица была сгенерирована в .NET 4.0 (см. Комментарий Леви Ботельо ниже, в котором говорится, что кодировка в .NET 4.5 немного отличается).

Редактировать:

Я добавил вторую таблицу с кодировками для .NET 4.5.Смотрите этот ответ: https://stackoverflow.com/a/21771206/216440

ПРАВКА 2:

Поскольку людям, похоже, нравятся эти таблицы, я подумал, что вам может понравиться исходный код, который генерирует таблицу, чтобы вы могли поиграть сами.Это простое консольное приложение на C #, которое может быть настроено как на .NET 4.0, так и на 4.5:

using System;
using System.Collections.Generic;
using System.Text;
// Need to add a Reference to the System.Web assembly.
using System.Web;

namespace UriEncodingDEMO2
{
    class Program
    {
        static void Main(string[] args)
        {
            EncodeStrings();

            Console.WriteLine();
            Console.WriteLine("Press any key to continue...");
            Console.Read();
        }

        public static void EncodeStrings()
        {
            string stringToEncode = "ABCD" + "abcd"
            + "0123" + " !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~" + "ĀāĒēĪīŌōŪū";

            // Need to set the console encoding to display non-ASCII characters correctly (eg the 
            //  Latin A-Extended characters such as ĀāĒē...).
            Console.OutputEncoding = Encoding.UTF8;

            // Will also need to set the console font (in the console Properties dialog) to a font 
            //  that displays the extended character set correctly.
            // The following fonts all display the extended characters correctly:
            //  Consolas
            //  DejaVu Sana Mono
            //  Lucida Console

            // Also, in the console Properties, set the Screen Buffer Size and the Window Size 
            //  Width properties to at least 140 characters, to display the full width of the 
            //  table that is generated.

            Dictionary<string, Func<string, string>> columnDetails =
                new Dictionary<string, Func<string, string>>();
            columnDetails.Add("Unencoded", (unencodedString => unencodedString));
            columnDetails.Add("UrlEncoded",
                (unencodedString => HttpUtility.UrlEncode(unencodedString)));
            columnDetails.Add("UrlEncodedUnicode",
                (unencodedString => HttpUtility.UrlEncodeUnicode(unencodedString)));
            columnDetails.Add("UrlPathEncoded",
                (unencodedString => HttpUtility.UrlPathEncode(unencodedString)));
            columnDetails.Add("EscapedDataString",
                (unencodedString => Uri.EscapeDataString(unencodedString)));
            columnDetails.Add("EscapedUriString",
                (unencodedString => Uri.EscapeUriString(unencodedString)));
            columnDetails.Add("HtmlEncoded",
                (unencodedString => HttpUtility.HtmlEncode(unencodedString)));
            columnDetails.Add("HtmlAttributeEncoded",
                (unencodedString => HttpUtility.HtmlAttributeEncode(unencodedString)));
            columnDetails.Add("HexEscaped",
                (unencodedString
                    =>
                    {
                        // Uri.HexEscape can only handle the first 255 characters so for the 
                        //  Latin A-Extended characters, such as A, it will throw an 
                        //  ArgumentOutOfRange exception.                       
                        try
                        {
                            return Uri.HexEscape(unencodedString.ToCharArray()[0]);
                        }
                        catch
                        {
                            return "[OoR]";
                        }
                    }));

            char[] charactersToEncode = stringToEncode.ToCharArray();
            string[] stringCharactersToEncode = Array.ConvertAll<char, string>(charactersToEncode,
                (character => character.ToString()));
            DisplayCharacterTable<string>(stringCharactersToEncode, columnDetails);
        }

        private static void DisplayCharacterTable<TUnencoded>(TUnencoded[] unencodedArray,
            Dictionary<string, Func<TUnencoded, string>> mappings)
        {
            foreach (string key in mappings.Keys)
            {
                Console.Write(key.Replace(" ", "[space]") + " ");
            }
            Console.WriteLine();

            foreach (TUnencoded unencodedObject in unencodedArray)
            {
                string stringCharToEncode = unencodedObject.ToString();
                foreach (string columnHeader in mappings.Keys)
                {
                    int columnWidth = columnHeader.Length + 1;
                    Func<TUnencoded, string> encoder = mappings[columnHeader];
                    string encodedString = encoder(unencodedObject);

                    // ASSUMPTION: Column header will always be wider than encoded string.
                    Console.Write(encodedString.Replace(" ", "[space]").PadRight(columnWidth));
                }
                Console.WriteLine();
            }
        }
    }
}

Вы должны кодировать только имя пользователя или другую часть URL-адреса, которая может быть недопустимой.URL-кодирование URL-адреса может привести к проблемам, поскольку что-то вроде этого:

string url = HttpUtility.UrlEncode("http://www.google.com/search?q=Example");

Уступит

http%3a%2f%2fwww.google.com%2fsearch%3fq%3 пример

Очевидно, что это не сработает должным образом.Вместо этого вы должны закодировать ТОЛЬКО значение пары ключ / значение в строке запроса, например:

string url = "http://www.google.com/search?q=" + HttpUtility.UrlEncode("Example");

Надеюсь, это поможет.Кроме того, поскольку тидяй как уже упоминалось, вам все равно нужно будет убедиться, что недопустимые символы имени файла удалены, иначе файловой системе не понравится путь.

С тех пор как Платформа .NET Framework 4.5 и .NET Стандарт 1.0 вы должны использовать WebUtility.UrlEncode.Преимущества перед альтернативами:

  1. Это часть .NET Framework 4.5+, .NET Core 1.0+, .NET Standard 1.0+, UWP 10.0+, а также всех платформ Xamarin. HttpUtility, будучи доступным в .NET Framework ранее (.NET Framework 1.1+), становится доступным на других платформах намного позже (.NET Core 2.0+, .NET Standard 2.0+) и по-прежнему недоступен в UWP (см. связанный с этим вопрос).

  2. В .NET Framework это проживает в System.dll, поэтому он не требует никаких дополнительных ссылок, в отличие от HttpUtility.

  3. IT правильно экранирует символы для URL-адресов, в отличие от Uri.EscapeUriString (см. комментарии к ответу drweb86).

  4. IT не имеет никаких ограничений на длину строки, в отличие от Uri.EscapeDataString (см. связанный с этим вопрос), так что его можно использовать, например, для запросов POST.

Лучший способ - это использовать

Uri.EscapeUriString

чтобы не ссылаться на Полный профиль .net 4.

Леви Ботельо прокомментировал, что таблица кодировок, которая была сгенерирована ранее, больше не является точной для .NET 4.5, поскольку кодировки немного изменились между .NET 4.0 и 4.5.Итак, я восстановил таблицу для .NET 4.5:

Unencoded UrlEncoded UrlEncodedUnicode UrlPathEncoded WebUtilityUrlEncoded EscapedDataString EscapedUriString HtmlEncoded HtmlAttributeEncoded WebUtilityHtmlEncoded HexEscaped
A         A          A                 A              A                    A                 A                A           A                    A                     %41
B         B          B                 B              B                    B                 B                B           B                    B                     %42

a         a          a                 a              a                    a                 a                a           a                    a                     %61
b         b          b                 b              b                    b                 b                b           b                    b                     %62

0         0          0                 0              0                    0                 0                0           0                    0                     %30
1         1          1                 1              1                    1                 1                1           1                    1                     %31

[space]   +          +                 %20            +                    %20               %20              [space]     [space]              [space]               %20
!         !          !                 !              !                    %21               !                !           !                    !                     %21
"         %22        %22               "              %22                  %22               %22              &quot;      &quot;               &quot;                %22
#         %23        %23               #              %23                  %23               #                #           #                    #                     %23
$         %24        %24               $              %24                  %24               $                $           $                    $                     %24
%         %25        %25               %              %25                  %25               %25              %           %                    %                     %25
&         %26        %26               &              %26                  %26               &                &amp;       &amp;                &amp;                 %26
'         %27        %27               '              %27                  %27               '                &#39;       &#39;                &#39;                 %27
(         (          (                 (              (                    %28               (                (           (                    (                     %28
)         )          )                 )              )                    %29               )                )           )                    )                     %29
*         *          *                 *              *                    %2A               *                *           *                    *                     %2A
+         %2b        %2b               +              %2B                  %2B               +                +           +                    +                     %2B
,         %2c        %2c               ,              %2C                  %2C               ,                ,           ,                    ,                     %2C
-         -          -                 -              -                    -                 -                -           -                    -                     %2D
.         .          .                 .              .                    .                 .                .           .                    .                     %2E
/         %2f        %2f               /              %2F                  %2F               /                /           /                    /                     %2F
:         %3a        %3a               :              %3A                  %3A               :                :           :                    :                     %3A
;         %3b        %3b               ;              %3B                  %3B               ;                ;           ;                    ;                     %3B
<         %3c        %3c               <              %3C                  %3C               %3C              &lt;        &lt;                 &lt;                  %3C
=         %3d        %3d               =              %3D                  %3D               =                =           =                    =                     %3D
>         %3e        %3e               >              %3E                  %3E               %3E              &gt;        >                    &gt;                  %3E
?         %3f        %3f               ?              %3F                  %3F               ?                ?           ?                    ?                     %3F
@         %40        %40               @              %40                  %40               @                @           @                    @                     %40
[         %5b        %5b               [              %5B                  %5B               [                [           [                    [                     %5B
\         %5c        %5c               \              %5C                  %5C               %5C              \           \                    \                     %5C
]         %5d        %5d               ]              %5D                  %5D               ]                ]           ]                    ]                     %5D
^         %5e        %5e               ^              %5E                  %5E               %5E              ^           ^                    ^                     %5E
_         _          _                 _              _                    _                 _                _           _                    _                     %5F
`         %60        %60               `              %60                  %60               %60              `           `                    `                     %60
{         %7b        %7b               {              %7B                  %7B               %7B              {           {                    {                     %7B
|         %7c        %7c               |              %7C                  %7C               %7C              |           |                    |                     %7C
}         %7d        %7d               }              %7D                  %7D               %7D              }           }                    }                     %7D
~         %7e        %7e               ~              %7E                  ~                 ~                ~           ~                    ~                     %7E

Ā         %c4%80     %u0100            %c4%80         %C4%80               %C4%80            %C4%80           Ā           Ā                    Ā                     [OoR]
ā         %c4%81     %u0101            %c4%81         %C4%81               %C4%81            %C4%81           ā           ā                    ā                     [OoR]
Ē         %c4%92     %u0112            %c4%92         %C4%92               %C4%92            %C4%92           Ē           Ē                    Ē                     [OoR]
ē         %c4%93     %u0113            %c4%93         %C4%93               %C4%93            %C4%93           ē           ē                    ē                     [OoR]
Ī         %c4%aa     %u012a            %c4%aa         %C4%AA               %C4%AA            %C4%AA           Ī           Ī                    Ī                     [OoR]
ī         %c4%ab     %u012b            %c4%ab         %C4%AB               %C4%AB            %C4%AB           ī           ī                    ī                     [OoR]
Ō         %c5%8c     %u014c            %c5%8c         %C5%8C               %C5%8C            %C5%8C           Ō           Ō                    Ō                     [OoR]
ō         %c5%8d     %u014d            %c5%8d         %C5%8D               %C5%8D            %C5%8D           ō           ō                    ō                     [OoR]
Ū         %c5%aa     %u016a            %c5%aa         %C5%AA               %C5%AA            %C5%AA           Ū           Ū                    Ū                     [OoR]
ū         %c5%ab     %u016b            %c5%ab         %C5%AB               %C5%AB            %C5%AB           ū           ū                    ū                     [OoR]

Столбцы представляют кодировки следующим образом:

  • UrlEncoded ( Кодированный URL ): HttpUtility.UrlEncode
  • UrlEncodedUnicode UrlEncodedUnicode: HttpUtility.UrlEncodeUnicode
  • UrlPathEncoded Закодированный: HttpUtility.UrlPathEncode
  • WebUtilityUrlEncoded Веб - утилита , закодированная: WebUtility.UrlEncode
  • EscapedDataString ( экранированный параметр ): Uri.EscapeDataString
  • Избегающий управления: Uri.EscapeUriString
  • HtmlEncoded Закодированный: HttpUtility.HtmlEncode
  • HtmlAttributeEncoded Закодированный: HttpUtility.HtmlAttributeEncode
  • WebUtilityHtmlEncoded Веб - утилиты htmlencoded: WebUtility.HtmlEncode
  • Шестиугольник: Uri.HexEscape

Примечания:

  1. HexEscape может обрабатывать только первые 255 символов.Поэтому он генерирует исключение ArgumentOutOfRange для латинских символов с расширением A (например, Á).

  2. Эта таблица была сгенерирована в .NET 4.5 (см. Ответ https://stackoverflow.com/a/11236038/216440 для кодировок, относящихся к .NET 4.0 и ниже).

Редактировать:

  1. В результате ответа Discord я добавил новые методы WebUtility UrlEncode и HtmlEncode, которые были введены в .NET 4.5.

Кодирование URL-адресов в .NET простое.Использование:

System.Web.HttpUtility.UrlEncode(string url)

Если это будет расшифровано для получения имени папки, вам все равно нужно будет исключить символы, которые нельзя использовать в именах папок (*, ?, / и т.д.)

Если вы не видите System.Web, измените настройки вашего проекта.Целевой платформой должна быть ".NET Framework 4" вместо "Профиль клиента .NET Framework 4".

.NET - реализация UrlEncode не соответствует RFC 3986.

  1. Некоторые символы не закодированы, но должны быть закодированы.В !()* символы перечислены в разделе 2.2 RFC как зарезервированные символы, которые еще должны быть закодированы.СЕТИ не удается закодировать эти символы.

  2. Некоторые символы закодированы, но таковыми быть не должны.В .-_ символы не перечислены в разделе 2.2 RFC как зарезервированные символы, которые еще не должны быть закодированы .NET ошибочно кодирует эти символы.

  3. RFC указывает, что для обеспечения согласованности реализации должны использовать шестнадцатеричный код в верхнем регистре, где .NET создает шестнадцатеричный код в нижнем регистре.

Я написал метод C #, который кодирует URL-адреса ВСЕХ символов:

    /// <summary>
    /// !#$345Hf} → %21%23%24%33%34%35%48%66%7D
    /// </summary>
    public static string UrlEncodeExtended( string value )
    {
        char[] chars = value.ToCharArray();
        StringBuilder encodedValue = new StringBuilder();
        foreach (char c in chars)
        {
            encodedValue.Append( "%" + ( (int)c ).ToString( "X2" ) );
        }
        return encodedValue.ToString();
    }

В идеале они должны входить в класс под названием "FileNaming" или, возможно, просто переименовать Encode в "FileNameEncode".Примечание:они не предназначены для обработки полных путей, только имен папок и / или файлов.В идеале вы бы сначала разделили ("/") ваш полный путь, а затем проверили фрагменты.И, очевидно, вместо объединения вы могли бы просто добавить символ "%" в список символов, не разрешенных в Windows, но я думаю, что так это более полезно / читаемо / фактически.Decode() - это точно то же самое, но переключает Replace(Uri.HexEscape(s[0]), s) "экранированный" символ.

public static List<string> urlEncodedCharacters = new List<string>
{
  "/", "\\", "<", ">", ":", "\"", "|", "?", "%" //and others, but not *
};
//Since this is a superset of urlEncodedCharacters, we won't be able to only use UrlEncode() - instead we'll use HexEncode
public static List<string> specialCharactersNotAllowedInWindows = new List<string>
{
  "/", "\\", "<", ">", ":", "\"", "|", "?", "*" //windows dissallowed character set
};

    public static string Encode(string fileName)
    {
        //CheckForFullPath(fileName); // optional: make sure it's not a path?
        List<string> charactersToChange = new List<string>(specialCharactersNotAllowedInWindows);
        charactersToChange.AddRange(urlEncodedCharacters.
            Where(x => !urlEncodedCharacters.Union(specialCharactersNotAllowedInWindows).Contains(x)));   // add any non duplicates (%)

        charactersToChange.ForEach(s => fileName = fileName.Replace(s, Uri.HexEscape(s[0])));   // "?" => "%3f"

        return fileName;
    }

Спасибо @simon-tewsi за очень полезную таблицу выше!

В дополнение к ответу @Dan Herbert , Вы, мы должны кодировать только значения в целом.

Split имеет параметр params Split('&','=');выражение сначала разделяется на &, затем '=', так что нечетными элементами являются все значения, которые должны быть закодированы, как показано ниже.

public static void EncodeQueryString(ref string queryString)
{
    var array=queryString.Split('&','=');
    for (int i = 0; i < array.Length; i++) {
        string part=array[i];
        if(i%2==1)
        {               
            part=System.Web.HttpUtility.UrlEncode(array[i]);
            queryString=queryString.Replace(array[i],part);
        }
    }
}

Я думаю, что людей здесь отвлекло сообщение UrlEncode.URLEncoding - это не что вы хотите - вы хотите закодировать материал, который не будет работать в качестве имени файла в целевой системе.

Предполагая, что вам нужна некоторая общность - не стесняйтесь находить недопустимые символы в нескольких системах (macOS, Windows, Linux и Unix), объединяя их, чтобы сформировать набор символов для экранирования.

Что касается escape, шестнадцатеричный формат должен быть в порядке (замена символов на %XX).Преобразуйте каждый символ в байты UTF-8 и кодируйте все > 128, если вы хотите поддерживать системы, которые не используют unicode.Но есть и другие способы, такие как использование обратной косой черты "\" или HTML-кодировки """.Вы можете создать свой собственный.Все, что должна сделать любая система, это "закодировать" несовместимый символ.Вышеупомянутые системы позволяют вам воссоздать исходное имя, но также работает что-то вроде замены неправильных символов пробелами.

По той же касательной, что и выше, единственным, который можно использовать, является

Uri.EscapeDataString (Экранированный запрос)

-- Он кодирует все, что необходимо для OAuth, он не кодирует то, что OAuth запрещает кодировать, и кодирует пробел как %20, а не + (также в спецификации OATH) См.:RFC 3986.AFAIK, это последняя спецификация URI.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top