首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Uri.EscapeDataString() -无效URI: Uri字符串太长

Uri.EscapeDataString() -无效URI: Uri字符串太长
EN

Stack Overflow用户
提问于 2011-07-14 14:51:14
回答 6查看 22.7K关注 0票数 29

我在windows mobile上使用了紧凑的框架/C#。

在我的应用程序中,我通过序列化对象并使用HttpWebRequest/POST请求将信息发送到服务器,将数据上传到服务器。在服务器上,post数据被反序列化并保存到数据库中。

前几天,我意识到我在post数据(符号等)中的特殊字符有问题。所以我在方法中引入了Uri.EscapeDataString(),一切都很好。

然而,今天我发现,当应用程序试图上传大量数据时,存在一个问题(我不知道目前到底什么是“大”!)

现有代码(某种形式)

代码语言:javascript
复制
var uploadData = new List<Things>();

uploadData.Add(new Thing() { Name = "Test 01" });
uploadData.Add(new Thing() { Name = "Test 02" });
uploadData.Add(new Thing() { Name = "Test with an & Ampersand " }); // Do this a lot!!

var postData = "uploadData=" + Uri.EscapeDataString(JsonConvert.SerializeObject(uploadData, new IsoDateTimeConverter()));

问题

对Uri.EscapeDataString()的调用将导致以下异常:

System.UriFormatException:无效URI: Uri字符串太长。

问题

是否有其他方法来准备上传的数据?

据我所见,HttpUtility (它有自己的编码/解码方法)无法用于紧凑的框架。

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2012-05-25 13:26:17

或者您可以简单地拆分字符串并为每个块调用Uri.EscapeDataString(string),以避免重新实现该函数。

示例代码:

代码语言:javascript
复制
        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)));
            }
        }
票数 37
EN

Stack Overflow用户

发布于 2017-10-04 13:51:28

“阿尔贝托·德·保拉”的答案是好的。

尽管如此,解除转义数据的难度要大一些,因为您必须避免在编码字符中间剪切编码的字符串(否则会破坏原始字符串的完整性)。

下面是我解决这个问题的方法:

代码语言:javascript
复制
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;
}

为了测试这些功能:

代码语言:javascript
复制
var testString = "long string to encode";
var encodedString = EncodeString(testString);
var decodedString = DecodeString(encodedString);

Console.WriteLine(decodedString == testString ? "integrity respected" : "integrity broken");

希望这能帮助避免头痛;)

票数 4
EN

Stack Overflow用户

发布于 2012-08-28 18:08:56

代码语言:javascript
复制
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();
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6695208

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档