Кодирование URL с помощью C#
у меня есть приложение, которое отправляет запрос POST на программное обеспечение форума VB и регистрирует кого-то (без установки куки или чего-либо еще).
после того, как пользователь вошел в систему, я создаю переменную, которая создает путь на локальном компьютере.
c:tempfolderdateusername
проблема в том, что некоторые имена пользователей бросают исключение "незаконные символы". Например, если мое имя пользователя было mas|fenix
это вызовет исключение..
Path.Combine( _
Environment.GetFolderPath(System.Environment.SpecialFolder.CommonApplicationData), _
DateTime.Now.ToString("ddMMyyhhmm") + "-" + form1.username)
Я не хотите удалить его из строки, но папка с их именем пользователя создается через FTP на сервере. И это приводит меня ко второму вопросу. Если я создаю папку на сервере, могу ли я оставить "незаконные символы"? Я только спрашиваю об этом, потому что сервер основан на Linux, и я не уверен, принимает ли его Linux или нет.
EDIT: кажется, что URL-кодирование-это не то, что я хочу.. Вот что я хочу сделать:
old username = mas|fenix
new username = mas%xxfenix
где %xx-значение ASCII или любое другое значение, которое будет легко идентифицировать символ.
12 ответов:
Edit: обратите внимание, что этот ответ теперь устарел. Смотрите ответ Сергея Кучука ниже для лучшего исправления
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 < < %3C = %3d %3d = %3D = = = %3D > %3e %3e > %3E %3E > > %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
Примечания:
HexEscape
может обрабатывать только первые 255 символов. Поэтому он бросаетArgumentOutOfRange
исключение для латинских а-расширенных символов (например Ля.)эта таблица была создана в .NET 4.0 (см. комментарий Levi Botelho ниже, в котором говорится, что кодировка в .NET 4.5 немного отличается).
EDIT:
я добавил вторую таблицу с кодировками для .NET 4.5. Смотрите этот ответ:https://stackoverflow.com/a/21771206/216440
EDIT 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 в%3А%2Ф%2fwww.Гугл.в COM%2fsearch%3fq%3dExample
Это, очевидно, не будет работать хорошо. Вместо этого вы должны кодировать только значение пары ключ / значение в строке запроса, например:
string url = "http://www.google.com/search?q=" + HttpUtility.UrlEncode("Example");
надеюсь, что помогает. Также, как teedyay упоминалось, вам все равно нужно будет убедиться, что незаконные символы имени файла удалены, иначе файловой системе не понравится путь.
С .NET Framework 4.5 можно использовать
WebUtility.UrlEncode
.во-первых, это проживает в
System.dll
, поэтому он не требует никаких дополнительных ссылок.во-вторых, это правильно экранирует символы для URL в отличие от
Uri.EscapeUriString
(см. комментарии к ответу drweb86).в-третьих, это не имеет никаких ограничений на длину строки в отличие от
Uri.EscapeDataString
(см. обзоры вопрос), так что он может быть использован для почтовых запросов, например.в-четвертых, это доступно на WinRT в отличие от
HttpUtility
(см. вопрос).
Levi Botelho прокомментировал, что таблица кодировок, которая была ранее сгенерирована, больше не является точной для .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 " " " %22 # %23 %23 # %23 %23 # # # # %23 $ %24 %24 $ %24 %24 $ $ $ $ %24 % %25 %25 % %25 %25 %25 % % % %25 & %26 %26 & %26 %26 & & & & %26 ' %27 %27 ' %27 %27 ' ' ' ' %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 < < < %3C = %3d %3d = %3D %3D = = = = %3D > %3e %3e > %3E %3E %3E > > > %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
Примечания:
HexEscape может обрабатывать только первые 255 символов. Поэтому он выдает исключение ArgumentOutOfRange для латинский а-расширенные символы (например, а).
эта таблица была создана в .NET 4.5 (см. ответ https://stackoverflow.com/a/11236038/216440 для кодировок, относящихся к .NET 4.0 и ниже).
EDIT:
- в результате ответа Discord я добавил новые методы Webutility UrlEncode и HtmlEncode, которые были введены в .NET 4.5.
кодирование Url легко в. NET. Use:
System.Web.HttpUtility.UrlEncode(string url)
Если это будет декодировано, чтобы получить имя папки, вам все равно нужно будет исключить символы, которые не могут быть использованы в именах папок ( * ,?, /, прием.)
Если вы не видите системы.Web, измените настройки проекта. Целевая платформа должна быть ".NET Framework 4 "вместо" .NET Framework 4 Client Profile"
интернет .Объем реализации
UrlEncode
не соответствует требованиям RFC 3986.
некоторые символы не кодируются, но должны быть. Элемент
!()*
символы перечислены в разделе 2.2 RFC как зарезервированные символы, которые должны быть закодированы, но .NET не может кодировать эти символы.некоторые символы закодированы, но не должны быть. Элемент
.-_
символы не перечислены в разделе 2.2 RFC в качестве зарезервированного символа, который не должен быть encoded yet .NET ошибочно кодирует эти символы.RFC указывает, что для обеспечения согласованности реализации должны использовать верхний регистр HEXDIG, где .NET создает нижний регистр HEXDIG.
в идеале это могло бы идти в класс под названием "файлов" или просто переименовать кодировать "FileNameEncode". Примечание: они не предназначены для обработки полных путей, только имена папок и/или файлов. В идеале вы должны сначала разделить ("/") свой полный путь, а затем проверить части. И, очевидно, вместо объединения вы можете просто добавить символ " % " в список символов, запрещенных в Windows, но я думаю, что это более полезно/читаемо/фактическим образом. Decode () точно такой же, но переключает Заменить(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 за очень полезную таблицу выше!
Я написал метод C#, который url-кодирует все символы:
/// <summary> /// !#5Hf} → %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(); }
в дополнение к ответу @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); } } }