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

340

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

masfenix
источник
Включите это, чтобы сделать файловые системы безопасными именами папок: http://stackoverflow.com/questions/333175/is-there-a-way-of-making-strings-file-path-safe-in-c
missaghi

Ответы:

191

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

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

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

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

Грегори Бимер
источник
5
этот ответ устарел сейчас. Прочитайте несколько ответов ниже - начиная с .net45, это может быть правильным решением: msdn.microsoft.com/en-us/library/…
blueberryfields
1
Для FTP каждая часть Uri (имя папки или файла) может быть построена с использованием Uri.EscapeDataString (fileOrFolderName), допускающего использование всех символов, не совместимых с Uri (пробелы, юникод ...). Например, чтобы разрешить любой символ в имени файла, используйте: req = (FtpWebRequest) WebRequest.Create (new Uri (path + "/" + Uri.EscapeDataString (filename))); Используя HttpUtility.UrlEncode () замените пробелы на знаки плюс (+). Правильное поведение для поисковых систем, но неверное для имен файлов / папок.
Рено Бансел
asp.net блокирует большую часть xss в URL, когда вы получаете предупреждение, когда вы пытаетесь добавить скрипт js A potentially dangerous Request.Path value was detected from the client.
Изучение
511

Я экспериментировал с различными методами .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" + " !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~" + "ĀāĒēĪīŌōŪū";

            // 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();
            }
        }
    }
}
Саймон Тьюси
источник
2
Это фантастический ответ. Оказывается, я хотел использовать Uri.EscapeDataString и не включать System.Web. Спасибо за этот стол.
Серави
7
Обратите внимание, что это уже не на 100% точно. Некоторые функции немного изменились между .NET 4 и .NET 4.5. См. Stackoverflow.com/q/20003106/1068266 .
Леви Ботельо
2
@Levi: Спасибо за внимание. Я добавил второй ответ с таблицей для .NET 4.5. Я отредактировал исходный ответ для ссылки на вторую таблицу.
Саймон Тьюси
Обратите внимание, что в документации .NET написано Не использовать; предназначен только для совместимости браузера. Используйте UrlEncode. , но этот метод кодирует много других нежелательных символов. Самый близкий Uri.EscapeUriString, но остерегайтесь, он не поддерживает nullаргумент.
Андрей
1
Я забыл упомянуть, мой комментарий выше для UrlPathEncode. Так что в основном заменить UrlPathEncodeна Uri.EscapeUriString.
Андрей
279

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

Дэн Герберт
источник
34
Использование метода HttpUtility.UrlPathEncode должно предотвратить проблему, которую вы здесь описываете.
vipirtti
12
@DJ Pirtu: Это правда, что UrlPathEncode не будет вносить эти нежелательные изменения в путь, однако он также не будет ничего кодировать после ?(поскольку предполагается, что строка запроса уже закодирована). В примере Дэна Герберта, похоже, он притворяется Example, что текст требует кодировки, поэтому HttpUtility.UrlPathEncode("http://www.google.com/search?q=Example");не будет работать. Попробуйте это с ?q=Ex&ple(где желаемый результат ?q=Ex%26ple). Это не будет работать, потому что (1) UrlPathEncode ничего не трогает после ?, и (2) UrlPathEncode все равно не кодирует &.
Тим Гудман
1
Смотрите здесь: connect.microsoft.com/VisualStudio/feedback/details/551839/… Я должен добавить, что, конечно, хорошо, что UrlPathEncode не кодирует &, потому что это необходимо для разделения параметров строки запроса. Но бывают случаи, когда вам нужны закодированные амперсанды.
Тим Гудман
10
HttpUtility сменил WebUtility в последних версиях, сэкономьте немного времени :)
Wiseman
190

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

Uri.EscapeUriString

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

Сергей Кучук
источник
1
Полностью согласен, так как часто «Профиль клиента» достаточно для приложений, использующих System.Net, но не использующих System.Web ;-)
hfrmobile
6
OP говорит о проверке совместимости файловой системы, поэтому это не сработает. Набор запрещенных символов Windows - это [["/", "\\", "<", ">", ":", "\" "," | ","? "," * "] ', Но многие из них не кодироваться с помощью EscapedUriString (см. таблицу ниже - спасибо за эту таблицу @Simon Tewsi) ... "создает путь на своем локальном компьютере" -OP UrlEncoded решает почти все проблемы, но не решает проблема с "%" или "% 3f" в исходном вводе, так как "декодирование" теперь будет отличаться от исходного.
m1m1k
6
просто чтобы прояснить: этот ответ не будет
работать
1
Кроме того, начиная с .NET Framework 4.5, профиль клиента был прекращен, и доступен только полный распространяемый пакет.
twomm
29
stackoverflow.com/a/34189188/3436164 Использовать Uri.EscapeDataStringНЕ Uri.EscapeUriStringПрочитайте этот комментарий, он мне помог.
ykadaru
181

Начиная с .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. Это отличие от правильно экранирует символы для URLUri.EscapeUriString (см. Комментарии к ответу drweb86 ).

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

Асария
источник
Мне нравится, как он кодирует, используя "+" вместо% 20 для пробелов ... но этот по-прежнему не удаляет "из URL-адреса и дает мне недопустимый URL-адрес ... да ладно ... просто придется заменить (" "" "", "")
Петр Кула
85

Леви Ботельхо прокомментировал, что таблица кодировок, которая была сгенерирована ранее, больше не является точной для .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.
Саймон Тьюси
источник
2
Нет, не пользователь UrlPathEncode - даже MSDN говорит, что его не следует использовать. Это было собрано,
Джефф
Является ли Server.URLEncode еще одним вариантом этой темы? Это генерирует какой-либо другой результат?
ALEXintlsos
2
@ALEX: в ASP.NET объект Server является экземпляром HttpServerUtility. Используя декомпилятор dotPeek, я взглянул на HttpServerUtility.UrlEncode. Он просто вызывает HttpUtility.UrlEncode, поэтому выходные данные двух методов будут идентичны.
Саймон Тьюси
Кажется, что даже при таком переизбытке методов кодирования все они все равно довольно эффектно терпят неудачу для чего-либо выше Latin-1, такого как → или ☠. (Похоже, что UrlEncodedUnicode, по крайней мере, пытается поддерживать Unicode, но устарел / отсутствует.)
brianary
Саймон, ты можешь просто интегрировать этот ответ в принятый ответ? было бы хорошо иметь это в одном ответе. Вы можете интегрировать его и сделать заголовок h1 в нижней части этого ответа, или объединить в одной таблице и отметить разные строки, например: (Net4.0) ? %3f................................ (Net4.5) ? %3f ..................................
T.Todua
60

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

System.Web.HttpUtility.UrlEncode(string url)

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

teedyay
источник
Кодирует ли он каждый символ, который не является частью алфавита?
Masfenix
1
Кодировка URL преобразует символы, которые не разрешены в URL, в эквиваленты символьной сущности. Список небезопасных персонажей: blooberry.com/indexdot/html/topics/urlencoding.htm
Ян Робинсон,
Ссылка MSDN на HttpUtility.UrlКод: msdn.microsoft.com/en-us/library/4fkewx0t.aspx
Ян Робинсон,
11
Хорошей практикой является использование полной части System.Web ... в вашем ответе, это сэкономит многим людям немного времени :) спасибо
Лиам
3
Это опасно: не все символы URL должны быть закодированы, только значения параметров строки запроса. Способ, которым вы предлагаете, будет также кодировать &, необходимый для создания нескольких параметров в строке запроса. Задача заключается в кодировании каждого значения параметров, если это необходимо
Марко Стаффоли
12

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

полезным
источник
1
По моему мнению, разработчики должны знать о «.NET Profiles», и они должны использовать правильный для своих целей! Просто добавить полный профиль, чтобы получить (например, System.Web), не зная, почему они добавляют полный профиль, не очень разумно. Используйте «Профиль клиента» для своих клиентских приложений и полный профиль только при необходимости (например, клиент WinForms или WPF должен использовать профиль клиента, а не полный профиль)! например, я не вижу причины использования HttpServerUtility в клиентском приложении ^^ ... если это необходимо, значит, что-то не так с дизайном приложения!
hfrmobile
4
В самом деле? Никогда не видели, чтобы клиентское приложение создавало URL? Что вы делаете для жизни - уборочные работы?
sproketboy
@hfrmobile: нет. Это все неправильно с моделью профиля (которая жила только один раз и была оставлена ​​в следующей версии). И это было очевидно с самого начала. Это сейчас для тебя очевидно? Подумайте сначала, не принимайте все «как есть», что msft пытается продать вам; П
Абатищев,
Извините, но я никогда не говорил, что клиент никогда не должен создавать / использовать URL. Пока используется .NET 4.0, пользователь должен заботиться об этом. Короче говоря: разработчики должны дважды подумать, прежде чем добавлять HttpServerUtility к клиенту. Есть и другие / лучшие способы, просто посмотрите ответ с 139 голосами или «Начиная с .NET Framework 4.5 вы можете использовать WebUtility.UrlEncode. Во-первых, он находится в System.dll, поэтому он не требует никаких дополнительных ссылок».
hfrmobile
9

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

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

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

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

Чарли
источник
4

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

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

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

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

Uri.EscapeDataString

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

Жерар ОНЕЙЛ
источник
3

Я написал метод 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

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

m1m1k
источник
также полезно: Path.GetInvalidFileNameChars()
m1m1k
да. Вот один из способов сделать это: foreach (char c в System.IO.Path.GetInvalidFileNameChars ()) {filename = filename.Replace (c, '_'); }
Netfed
0

В дополнение к ответу @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);
        }
    }
}
Давут Гюрбюз
источник