[英]Uri.EscapeDataString() - Invalid URI: The Uri string is too long
我在 windows 移動設備上使用緊湊型框架/C#。
在我的應用程序中,我通過序列化對象並使用 HttpWebRequest/POST 請求將信息向上發送來將數據上傳到服務器。 在服務器上,發布數據被反序列化並保存到數據庫中。
前幾天我意識到我在發布數據(和號等)中遇到了特殊字符的問題。 所以我在方法中引入了 Uri.EscapeDataString() ,一切都很好。
但是,今天我發現當應用程序嘗試上傳大量數據時會出現問題(我現在不確定究竟什么是“大”!)
現有代碼(種類)
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(它有自己的編碼/解碼方法)不適用於緊湊型框架。
或者您可以簡單地拆分您的字符串並為每個塊調用Uri.EscapeDataString(string)
,以避免重新實現 function。
示例代碼:
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)));
}
}
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();
“Alberto de Paola”的答案很好。
盡管如此,要對轉義的數據進行轉義有點棘手,因為您必須避免在編碼字符的中間切割編碼字符串(否則您將破壞原始字符串的完整性)。
這是我解決此問題的方法:
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;
}
要測試這些功能:
var testString = "long string to encode";
var encodedString = EncodeString(testString);
var decodedString = DecodeString(encodedString);
Console.WriteLine(decodedString == testString ? "integrity respected" : "integrity broken");
希望這可以幫助避免一些頭痛;)
我一直在使用 System.Web.HttpUtility.UrlEncode 並且似乎可以更好地處理較長的字符串。
使用System.Web.HttpUtility.UrlEncode
(基於this answer ):
value = HttpUtility.UrlEncode(value)
.Replace("!", "%21")
.Replace("(", "%28")
.Replace(")", "%29")
.Replace("*", "%2A")
.Replace("%7E", "~"); // undo escape
我需要另一個解決方案,因為 Pouki 的解決方案在處理 Cyrillic 並剪切符號時不起作用。
替代解決方案如下:
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();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.