it-roy-ru.com

Кодирование URL с использованием C #

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

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

c:\TempFolder\дата\имя пользователя

Проблема заключается в том, что некоторые имена пользователей выдают исключение «Недопустимые символы». Например, если бы мое имя пользователя было 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 или любое другое значение, которое легко идентифицирует символ.

287
masfenix

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

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

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

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

168
Gregory A Beamer

Я экспериментировал с различными методами .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: HttpUtility.UrlEncode

  • UrlEncodedUnicode: HttpUtility.UrlEncodeUnicode

  • UrlPathEncoded: HttpUtility.UrlPathEncode

  • EscapedDataString: Uri.EscapeDataString

  • EscapedUriString: Uri.EscapeUriString

  • HtmlEncoded: HttpUtility.HtmlEncode

  • HtmlAttributeEncoded: HttpUtility.HtmlAttributeEncode

  • HexEscaped: Uri.HexEscape

ЗАМЕТКИ: 

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

  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" + " !\"#$%&'()*+,-./:;<=>[email protected][\\]^_`{|}~" + "ĀāĒēĪīŌōŪū";

            // 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();
            }
        }
    }
}
442
Simon Tewsi

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

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

Даст 

hTTP% 3A% 2F% 2fwww.google.com% 2fsearch% 3fq% 3dExample

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

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

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

260
Dan Herbert

Лучше использовать

Uri.EscapeUriString

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

157
Siarhei Kuchuk

Начиная с .NET Framework 4.5 и .NET Standard 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. Это правильно экранирует символы для URL, в отличие от Uri.EscapeUriString (см. комментарии к ответу drweb86 ).

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

153
Athari

Леви Ботелхо прокомментировал, что таблица сгенерированных ранее кодировок больше не является точной для .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: HttpUtility.UrlEncode
  • UrlEncodedUnicode: HttpUtility.UrlEncodeUnicode
  • UrlPathEncoded: HttpUtility.UrlPathEncode
  • WebUtilityUrlEncoded: WebUtility.UrlEncode
  • EscapedDataString: Uri.EscapeDataString 
  • EscapedUriString: Uri.EscapeUriString 
  • HtmlEncoded: HttpUtility.HtmlEncode 
  • HtmlAttributeEncoded: HttpUtility.HtmlAttributeEncode 
  • WebUtilityHtmlEncoded: WebUtility.HtmlEncode 
  • HexEscaped: Uri.HexEscape

ЗАМЕТКИ: 

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

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

Правка: 

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

Url-кодирование легко в .NET. Использование:

System.Web.HttpUtility.UrlEncode(string url)

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

52
teedyay

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

12
useful

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

  1. Некоторые символы не закодированы, но должны быть. Символы !()* перечислены в разделе 2.2 RFC как зарезервированные символы, которые необходимо кодировать, но .NET не может кодировать эти символы.

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

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

9
Charlie

В идеале они должны быть в классе с именем «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 за очень полезную таблицу выше!

1
m1m1k

Я написал метод 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();
    }
1
Sergey

В дополнение к ответу @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);
        }
    }
}
0
Davut Gürbüz

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

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

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

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

Uri.EscapeDataString

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

0
Gerard ONeill