使用C#進行URL編碼

我有一個應用程序,該應用程序將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


#1樓

我一直在嘗試.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]

這些列表示的編碼以下: 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

筆記:

  1. HexEscape只能處理前255個字符。 所以,它爲拉丁A擴展字符(例如Ā)拋出ArgumentOutOfRange異常。

  2. 該表是在.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();
            }
        }
    }
}

#2樓

理想狀況下,將它們放在名爲「 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提供了上面很是有用的表!


#3樓

除了@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);
        }
    }
}

#4樓

UrlEncode的.NET實現不符合RFC 3986。

  1. 有些字符未編碼,但應該編碼。 !()*字符在RFC的2.2節中做爲必須保留的字符列出,但.NET沒法對這些字符進行編碼。

  2. 有些字符已編碼,但不該編碼。 RFC的2.2節中未將.-_字符列爲保留字符,但不該對其進行編碼。.NET錯誤地對這些字符進行了編碼。

  3. RFC規定,爲了保持一致,實現應使用大寫的HEXDIG,而.NET會生成小寫的HEXDIG。


#5樓

.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. Uri.EscapeUriString不一樣,它能夠正確地轉義URL字符 (請參見drweb86的答案的註釋 )。

  4. Uri.EscapeDataString (請參閱相關問題 )不一樣, Uri.EscapeDataString 字符串的長度沒有任何限制 ,所以能夠將其用於POST請求。

相關文章
相關標籤/搜索