我有一個應用程序,該應用程序將POST請求發送到VB論壇軟件並登陸某人(不設置cookie或任何東西)。 web
用戶登陸後,我將建立一個變量,該變量將在其本地計算機上建立路徑。 windows
c:\\ tempfolder \\ date \\用戶名 api
問題在於某些用戶名拋出「非法字符」異常。 例如,若是個人用戶名是mas|fenix
,它將引起異常。 服務器
Path.Combine( _ Environment.GetFolderPath(System.Environment.SpecialFolder.CommonApplicationData), _ DateTime.Now.ToString("ddMMyyhhmm") + "-" + form1.username)
我不想從字符串中刪除它,可是經過服務器上的FTP建立了一個帶有用戶名的文件夾。 這引出了個人第二個問題。 若是我在服務器上建立文件夾,能夠保留「非法字符」嗎? 我之因此只問這是由於服務器是基於Linux的,因此我不肯定Linux是否接受它。 cookie
編輯:彷佛URL編碼不是我想要的。這是我想作的: app
old username = mas|fenix new username = mas%xxfenix
其中%xx是ASCII值或任何其餘容易識別字符的值。 ide
我一直在嘗試.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]
這些列表示的編碼以下: this
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個字符。 所以,它爲拉丁A擴展字符(例如Ā)拋出ArgumentOutOfRange
異常。
該表是在.NET 4.0中生成的(請參閱下面的Levi Botelho的評論,其中說.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(); } } } }
理想狀況下,將它們放在名爲「 FileNaming」的類中,或者只是將Encode重命名爲「 FileNameEncode」。 注意:這些文件並不是旨在處理完整路徑,而僅用於處理文件夾和/或文件名。 理想狀況下,您將首先拆分(「 /」)您的完整路徑,而後檢查各個部分。 並且顯然可使用Windows不容許的字符列表中的「%」字符來代替工會,可是我認爲這種方式更加有用/可讀/實用。 Decode()徹底相同,可是使用字符切換了「轉義」的Replace(Uri.HexEscape(s [0]),s)。
public static List<string> urlEncodedCharacters = new List<string> { "/", "\\", "<", ">", ":", "\"", "|", "?", "%" //and others, but not * }; //Since this is a superset of urlEncodedCharacters, we won't be able to only use UrlEncode() - instead we'll use HexEncode public static List<string> specialCharactersNotAllowedInWindows = new List<string> { "/", "\\", "<", ">", ":", "\"", "|", "?", "*" //windows dissallowed character set }; public static string Encode(string fileName) { //CheckForFullPath(fileName); // optional: make sure it's not a path? List<string> charactersToChange = new List<string>(specialCharactersNotAllowedInWindows); charactersToChange.AddRange(urlEncodedCharacters. Where(x => !urlEncodedCharacters.Union(specialCharactersNotAllowedInWindows).Contains(x))); // add any non duplicates (%) charactersToChange.ForEach(s => fileName = fileName.Replace(s, Uri.HexEscape(s[0]))); // "?" => "%3f" return fileName; }
感謝@ simon-tewsi提供了上面很是有用的表!
除了@Dan Herbert的答案以外,您一般應該只編碼值。
Split具備參數參數Split('&','='); 表達式首先被&分隔,而後是'=',所以奇數元素都是要編碼的全部值,以下所示。
public static void EncodeQueryString(ref string queryString) { var array=queryString.Split('&','='); for (int i = 0; i < array.Length; i++) { string part=array[i]; if(i%2==1) { part=System.Web.HttpUtility.UrlEncode(array[i]); queryString=queryString.Replace(array[i],part); } } }
UrlEncode
的.NET實現不符合RFC 3986。
有些字符未編碼,但應該編碼。 !()*
字符在RFC的2.2節中做爲必須保留的字符列出,但.NET沒法對這些字符進行編碼。
有些字符已編碼,但不該編碼。 RFC的2.2節中未將.-_
字符列爲保留字符,但不該對其進行編碼。.NET錯誤地對這些字符進行了編碼。
RFC規定,爲了保持一致,實現應使用大寫的HEXDIG,而.NET會生成小寫的HEXDIG。
從.NET Framework 4.5和.NET Standard 1.0開始,您應該使用WebUtility.UrlEncode
。 相對替代品的優點:
它是.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中仍然不可用(請參閱相關問題 )。
在.NET Framework中,它駐留在System.dll
,所以與HttpUtility
不一樣,它不須要任何其餘引用。
與Uri.EscapeUriString
不一樣,它能夠正確地轉義URL字符 (請參見drweb86的答案的註釋 )。
與Uri.EscapeDataString
(請參閱相關問題 )不一樣, Uri.EscapeDataString
字符串的長度沒有任何限制 ,所以能夠將其用於POST請求。