Uri.EscapeDataString() - Invalid URI: The Uri string is too long

前端 未结 6 1662
难免孤独
难免孤独 2020-12-07 00:14

I\'m using compact framework/C# on windows mobile.

In my application I am uploading data to the server by serializing objects and using a HttpWebRequest/POST request

相关标签:
6条回答
  • 2020-12-07 00:54

    Use System.Web.HttpUtility.UrlEncode (based on this answer):

            value = HttpUtility.UrlEncode(value)
                .Replace("!", "%21")
                .Replace("(", "%28")
                .Replace(")", "%29")
                .Replace("*", "%2A")
                .Replace("%7E", "~"); // undo escape
    
    0 讨论(0)
  • 2020-12-07 00:55

    The answer of "Alberto de Paola" is good.

    Nonetheless, to unescape the escaped data is little bit trickier, because you have to avoid cutting the encoded string at the middle of an encoded char (or you will break the integrity of the original string).

    Here's my way of fixing this issue :

    public static string EncodeString(string str)
    {
        //maxLengthAllowed .NET < 4.5 = 32765;
        //maxLengthAllowed .NET >= 4.5 = 65519;
        int maxLengthAllowed = 65519;
        StringBuilder sb = new StringBuilder();
        int loops = str.Length / maxLengthAllowed;
    
        for (int i = 0; i <= loops; i++)
        {
            sb.Append(Uri.EscapeDataString(i < loops
                ? str.Substring(maxLengthAllowed * i, maxLengthAllowed)
                : str.Substring(maxLengthAllowed * i)));
        }
    
        return sb.ToString();
    }
    
    public static string DecodeString(string encodedString)
    {
        //maxLengthAllowed .NET < 4.5 = 32765;
        //maxLengthAllowed .NET >= 4.5 = 65519;
        int maxLengthAllowed = 65519;
    
        int charsProcessed = 0;
        StringBuilder sb = new StringBuilder();
    
        while (encodedString.Length > charsProcessed)
        {
            var stringToUnescape = encodedString.Substring(charsProcessed).Length > maxLengthAllowed
                ? encodedString.Substring(charsProcessed, maxLengthAllowed)
                : encodedString.Substring(charsProcessed);
    
            // If the loop cut an encoded tag (%xx), we cut before the encoded char to not loose the entire char for decoding
            var incorrectStrPos = stringToUnescape.Length == maxLengthAllowed ? stringToUnescape.IndexOf("%", stringToUnescape.Length - 4, StringComparison.InvariantCulture) : -1;
            if (incorrectStrPos > -1)
            {
                stringToUnescape = encodedString.Substring(charsProcessed).Length > incorrectStrPos
                    ? encodedString.Substring(charsProcessed, incorrectStrPos)
                    : encodedString.Substring(charsProcessed);
            }
    
            sb.Append(Uri.UnescapeDataString(stringToUnescape));
            charsProcessed += stringToUnescape.Length;
        }
    
        var decodedString = sb.ToString();
    
        // ensure the string is sanitized here or throw exception if XSS / SQL Injection is found
        SQLHelper.SecureString(decodedString);
        return decodedString;
    }
    

    To test these functions :

    var testString = "long string to encode";
    var encodedString = EncodeString(testString);
    var decodedString = DecodeString(encodedString);
    
    Console.WriteLine(decodedString == testString ? "integrity respected" : "integrity broken");
    

    Hope this can help avoiding some headaches ;)

    0 讨论(0)
  • 2020-12-07 00:56

    I needed another solution because the solution from Pouki does not work when Cyrillic is processed and symbol is cut.

    The alternative solution is as follow:

        protected const int MaxLengthAllowed = 32765;
        private static string UnescapeString(string encodedString)
        {
            var charsProccessed = 0;
    
            var sb = new StringBuilder();
    
            while (encodedString.Length > charsProccessed)
            {
                var isLastIteration = encodedString.Substring(charsProccessed).Length < MaxLengthAllowed;
    
                var stringToUnescape = isLastIteration
                    ? encodedString.Substring(charsProccessed)
                    : encodedString.Substring(charsProccessed, MaxLengthAllowed);
    
                while (!Uri.IsWellFormedUriString(stringToUnescape, UriKind.RelativeOrAbsolute) || stringToUnescape.Length == 0)
                {
                    stringToUnescape = stringToUnescape.Substring(0, stringToUnescape.Length - 1);
                }
    
                sb.Append(Uri.UnescapeDataString(stringToUnescape));
                charsProccessed += stringToUnescape.Length;
            }
    
            return sb.ToString();
        }
    
    0 讨论(0)
  • 2020-12-07 01:03

    Or you could simply split your string and call Uri.EscapeDataString(string) for each block, in order to avoid reimplementing the function.

    Sample Code:

            String value = "large string to encode";
            int limit = 2000;
    
            StringBuilder sb = new StringBuilder();
            int loops = value.Length / limit;
    
            for (int i = 0; i <= loops; i++)
            {
                if (i < loops)
                {
                    sb.Append(Uri.EscapeDataString(value.Substring(limit * i, limit)));
                }
                else
                {
                    sb.Append(Uri.EscapeDataString(value.Substring(limit * i)));
                }
            }
    
    0 讨论(0)
  • 2020-12-07 01:03
    StringBuilder stringBuilder = new StringBuilder();
    for (int i = 0; i < originalString.Length; i++)
    {
        if ((originalString[i] >= 'a' && originalString[i] <= 'z') || 
            (originalString[i] >= 'A' && originalString[i] <= 'Z') || 
            (originalString[i] >= '0' && originalString[i] <= '9'))
        {
            stringBuilder.Append(originalString[i]);
        }
        else
        {
            stringBuilder.AppendFormat("%{0:X2}", (int)originalString[i]);
        }
    }
    
    string result = stringBuilder.ToString();
    
    0 讨论(0)
  • 2020-12-07 01:11

    I have been using System.Web.HttpUtility.UrlEncode and seems to handle the longer strings much better.

    0 讨论(0)
提交回复
热议问题