Кодирование 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 или любое другое значение, которое легко идентифицирует символ.

14 ответов

Решение

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

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

Вы также можете откорректировать недопустимые символы и затем заменить, но это становится гораздо более сложным, так как вам потребуется некоторая форма конечного автомата (например, switch... case) для замены на правильные символы. поскольку 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: 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. Смотрите этот ответ: /questions/48018050/kodirovanie-url-s-ispolzovaniem-c/48018082#48018082

РЕДАКТИРОВАТЬ 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%3dExample

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

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

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

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

Uri.EscapeUriString

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

Начиная с .NET Framework 4.5 вы можете использовать WebUtility.UrlEncode,

Во-первых, он находится в System.dll, поэтому он не требует никаких дополнительных ссылок.

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

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

В-четвертых, он доступен на WinRT, в отличие от HttpUtility (см. связанный вопрос).

Леви Ботелхо прокомментировал, что таблица сгенерированных ранее кодировок больше не является точной для.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 (см. Ответ /questions/48018050/kodirovanie-url-s-ispolzovaniem-c/48018100#48018100 для кодировок, относящихся к.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 Client Profile"

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

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

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

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

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

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

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

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

Uri.EscapeDataString

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

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

Для пользователей .net core используйте это

      Microsoft.AspNetCore.Http.Extensions.UriHelper.Encode(Uri uri)

В дополнение к ответу @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);
        }
    }
}
Другие вопросы по тегам